题意:

  给出平面直角坐标系上的n个点的坐标,表示一个多边形蛋糕,先判断是否是凸多边形,若否,输出"I can't cut."。若是,则对这个蛋糕进行3角形剖分,切n-3次变成n-2份三角形蛋糕给小伙伴吃,但是每切一次需要一个费用,公式是:cost[i][j] = |xi + xj| * |yi + yj| % p 表示在两点i和j之间切一刀的费用。问最少费用是多少?

思路:

  判断是否凸多边形需要用到求凸包的Andrew算法,时间复杂度为O(nlogn),然后判断凸包内的点数是否为n就行了。(大白书p271)

  求最小费用需要用到分治的一些思想,当然主要还是dp。

  如下图的凸多边形(图来自这里),如果点1和点n还差1个点就成为三角形了,我们可以枚举这个点k,切两刀,取出K0(不能再切),变成K1和K2两块,以刚切的1->k和k->n这两条边为基边,继续分治切下去,直到剩下1个三角形为止。那么以edge[i][j]为基边来切开这个子凸多边形的费用是dp[i][j]=max(dp[i][j], dp[i][k]+dp[i][k]+cost[i][k]+cost[k][j]),所有点对的cost可以先求出来。注意在计算dp[i][j]时,dp[i][k]和dp[k][j]必须先求出来。

 //#include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <map>
#include <deque>
#include <algorithm>
#include <vector>
#include <iostream>
#define pii pair<int,int>
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define abs(x) ((x)<0?-(x):(x))
#define INF 0x3f3f3f3f
#define LL long long
using namespace std;
const double PI = acos(-1.0);
const int N=; struct node
{
int x,y;
node(){};
node(int x,int y):x(x),y(y){};
}Po[N], path[N];
int n, p, c[N][N], dp[N][N]; inline int cmp(node a,node b)
{
if(a.x==b.x) return a.y<b.y;
return a.x<b.x;
}
inline int cross(node A,node p1,node p2) //叉积,A是新来的点。若A在p1->p2左边,则结果为正。
{
return (p1.x-A.x)*(p2.y-A.y) - (p2.x-A.x)*(p1.y-A.y);
}
int get_cost(node a,node b){return abs(a.x+b.x)*abs(a.y+b.y)%p;} //在a和b之间切开的费用 int ConvexHull(node *u,int n,node *path) //求凸包,返回凸包中的点数
{
sort(u,u+n,cmp); //先按x再按y排序
int top=;
for(int i=; i<n; i++) //下凸包:从左到右
{
while(top> && cross(u[i],path[top-],path[top-])<= ) top--; //小于0,在右边
path[top++]=u[i];
}
int k=top;
for(int i=n-; i>=; i--) //上凸包:从右到左
{
while(top>k && cross(u[i],path[top-],path[top-])<= ) top--;
path[top++]=u[i];
}
if(n>) top--; //起点是重复了的,要去掉
return top;
} int cal()
{
if(n==) return ; //3点则0费用
memset(c,,sizeof(c));
for(int i=; i<n; i++) //任意两点间连一条边的费用c
for(int j=i+; j<n; j++)
c[i][j]=c[j][i]=get_cost( path[i], path[j] );
for(int i=; i<n; i++)
{
for (int j=; j<n; j++) dp[i][j]=INF;
dp[i][i+] = ; //相邻两个点不能连线,可视为费用为0.
}
for(int j=; j<n; j++) //升序
{
for(int i=j-; i>=; i--) //降序
{
for(int k=i+; k<j; k++) //枚举三角形顶点
dp[i][j]=min(dp[i][j], dp[i][k]+dp[k][j]+c[i][k]+c[k][j]);
}
}
return dp[][n-];
} int main()
{
//freopen("input.txt", "r", stdin);
while(~scanf("%d%d",&n,&p))
{
for(int i=; i<n; i++) scanf("%d%d",&Po[i].x,&Po[i].y);
if(ConvexHull(Po,n,path)<n) puts("I can't cut.");
else printf("%d\n", cal());
} return ;
}

AC代码

ZOJ 3537 Cake (区间DP,三角形剖分)的更多相关文章

  1. zoj 3537 Cake 区间DP (好题)

    题意:切一个凸边行,如果不是凸包直接输出.然后输出最小代价的切割费用,把凸包都切割成三角形. 先判断是否是凸包,然后用三角形优化. dp[i][j]=min(dp[i][j],dp[i][k]+dp[ ...

  2. 区间DP Zoj 3537 Cake 区间DP 最优三角形剖分

    下面是别人的解题报告的链接,讲解很详细,要注意细节的处理...以及为什么可以这样做 http://blog.csdn.net/woshi250hua/article/details/7824433 我 ...

  3. zoj 3537 Cake(区间dp)

    这道题目是经典的凸包的最优三角剖分,不过这个题目给的可能不是凸包,所以要提前判定一下是否为凸包,如果是凸包的话才能继续剖分,dp[i][j]表示已经排好序的凸包上的点i->j上被分割成一个个小三 ...

  4. ZOJ 3537 Cake(凸包+区间DP)

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3537 题目大意:给出一些点表示多边形顶点的位置,如果不是凸多边形 ...

  5. ZOJ 3537 Cake(凸包判定+区间DP)

    Cake Time Limit: 1 Second Memory Limit: 32768 KB You want to hold a party. Here's a polygon-shaped c ...

  6. ZOJ 3537 Cake 求凸包 区间DP

    题意:给出一些点表示多边形顶点的位置(如果多边形是凹多边形就不能切),切多边形时每次只能在顶点和顶点间切,每切一次都有相应的代价.现在已经给出计算代价的公式,问把多边形切成最多个不相交三角形的最小代价 ...

  7. zoj 3537 Cake (凸包确定+间隔dp)

    Cake Time Limit: 1 Second      Memory Limit: 32768 KB You want to hold a party. Here's a polygon-sha ...

  8. ZOJ 3537 Cake

    区间DP. 首先求凸包判断是否为凸多边形. 如果是凸多边形:假设现在要切割连续的一段点,最外面两个一定是要切一刀的,内部怎么切达到最优解就是求子区间最优解,因此可以区间DP. #include< ...

  9. ZOJ 3469Food Delivery(区间DP)

    Food Delivery Time Limit: 2 Seconds      Memory Limit: 65536 KB When we are focusing on solving prob ...

随机推荐

  1. Tomcat-redis-Nginx

    环境:centos7, Tomcat7, redis-3.2,Nginx1.8,jdk-8u60-linux-x64 Nginx反向代理tomcat,redis作会话共享 一.Nginx安装 解决依赖 ...

  2. 1.SJ-SLAM-14

    1.引言 SLAM:Simultaneous Localization and Mapping 同时定位与地图构建 搭载特定传感器的主体,在没有环境先验信息的情况下,于运动过程中建立环境的模型,同时估 ...

  3. jquery table表格 获取选中的某一行和某一列的值

    table class="table table-hover" id="test123"> <tr> <th width="4 ...

  4. node中的url模块解析结果

    1. URL模块作用: url 模块用于处理与解析 URL. 使用方法如下: const url = require('url'); 2. URL 字符串与 URL 对象 URL 字符串是结构化的字符 ...

  5. QRegExp解析

    正则表达式(regular expression)就是用一个“字符串”来描述一个特征,然后去验证另一个“字符串”是否符合这个特征.比如 表达式“ab+” 描述的特征是“一个 'a' 和 任意个 'b' ...

  6. [HNOI2010] 物品调度 fsk

    标签:链表+数论知识. 题解: 对于这道题,其实就是两个问题的拼凑,我们分开来看. 首先要求xi与yi.这个可以发现,x每增加1,则pos增加d:y每增加1,则pos增加1.然后,我们把x与y分别写在 ...

  7. Markdown - 如何给文本加下划线

    解决方法 Markdown可以和HTML的语法兼容,可以通过HTML的标签来实现效果: 写法 效果 <u>下划线</u> 下划线 这里解释下,u指的是underline下划线. ...

  8. Day2课后作业:三级菜单简单版

    menu = { '北京':{ '海淀':{ '五道口':{ 'soho':{}, '网易':{}, '谷歌':{} }, '中关村':{ '爱奇艺':{}, '汽车之家':{}, 'youku':{ ...

  9. 多线程:『GCD』详尽总结

    本文用来介绍 iOS 多线程中 GCD 的相关知识以及使用方法.这大概是史上最详细.清晰的关于 GCD 的详细讲解+总结的文章了.通过本文,您将了解到:1. GCD 简介2. GCD 任务和队列3. ...

  10. 【bzoj3033】太鼓达人

    3033: 太鼓达人 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 521  Solved: 399[Submit][Status][Discuss] ...