题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3537

题目大意:给出一些点表示多边形顶点的位置,如果不是凸多边形(凸包)则不能切,直接输出"I can't cut."
切多边形时每次只能在顶点和顶点间切,每切一次的花费为 cost(i, j) = |xi + xj| * |yi + yj| % p。
问把多边形切成最多个不相交三角形的最小代价是多少。

解题思路:先求出凸包,接着可以用区间DP解决,设dp[i][j]为以i为起点,j为终点的凸包被切成三角形的最小花费。
那么可以得到状态转移方程:dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j]+cost[i][k]+cost[k][j])。
不懂的可以看下图(非原创):

代码:

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<cmath>
#include<algorithm>
using namespace std;
const int INF=0x3f3f3f3f;
const int N=;
const double eps = 1e-; int n,mod;
int dp[N][N],cost[N][N]; struct P
{
double x, y;
P(double x=, double y=):x(x), y(y) {}
double add(double a, double b){
if(fabs(a+b)<eps*(fabs(a)+fabs(b))) return ;
return a+b;
}
P operator + (P p){
return P(add(x, p.x), add(y, p.y));
}
P operator - (P p){
return P(add(x, -p.x), add(y, -p.y));
}
P operator *(double d){
return P(x*d, y*d);
}
double dot(P p){ //点积
return add(x*p.x, y*p.y);
}
double det(P p){ //差积
return add(x*p.y, -y*p.x);
}
}ps[N]; double dist(P a, P b){
return sqrt((b-a).dot(b-a));
} bool cmp_x(const P& p, const P& q){
if(p.x!=q.x) return p.x < q.x;
return p.y < q.y;
} vector<P> convex_hull(P *ps, int n){
sort(ps,ps+n,cmp_x);
int k = ; //凸包顶点数
vector<P> qs(n*);
//构造凸包的下侧
for(int i=; i<n; i++)
{
while(k> && (qs[k-]-qs[k-]).det(ps[i]-qs[k-])<=) k--;
qs[k++] = ps[i];
}
//构造凸包的上侧
for(int i=n-,t=k; i>=; i--)
{
while(k>t && (qs[k-]-qs[k-]).det(ps[i]-qs[k-])<=) k--;
qs[k++] = ps[i];
}
qs.resize(k-);
return qs;
} int getcost(P p1,P p2){
return abs((int)p1.x+(int)p2.x)*abs((int)p1.y+(int)p2.y)%mod;
} int main(){
while(~scanf("%d%d",&n,&mod)){
for(int i=;i<n;i++){
scanf("%lf%lf",&ps[i].x,&ps[i].y);
}
vector<P>tp;
tp=convex_hull(ps,n);
if(tp.size()<n){
puts("I can't cut.");
continue;
}
//注意,用获得的凸包做DP,即使用tp做DP,保证凸包上的点的顺序
memset(cost,,sizeof(cost));
memset(dp,,sizeof(dp));
for(int i=;i<n;i++){
for(int j=i+;j<n;j++){
cost[i][j]=getcost(tp[i],tp[j]);
}
}
for(int len=;len<n;len++){
for(int i=;i+len<n;i++){
int j=i+len;
dp[i][j]=INF;
for(int k=i+;k<=j-;k++){
dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j]+cost[i][k]+cost[k][j]);
}
}
}
printf("%d\n",dp[][n-]);
}
return ;
}

ZOJ 3537 Cake(凸包+区间DP)的更多相关文章

  1. ZOJ - 3537 Cake (凸包+区间DP+最优三角剖分)

    Description You want to hold a party. Here's a polygon-shaped cake on the table. You'd like to cut t ...

  2. ZOJ 3537 Cake (区间DP,三角形剖分)

    题意: 给出平面直角坐标系上的n个点的坐标,表示一个多边形蛋糕,先判断是否是凸多边形,若否,输出"I can't cut.".若是,则对这个蛋糕进行3角形剖分,切n-3次变成n-2 ...

  3. ZOJ 3537 (凸包 + 区间DP)(UNFINISHED)

    #include "Head.cpp" const int N = 10007; int n, m; struct Point{ int x,y; bool operator &l ...

  4. 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 ...

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

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

  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]3541 Last Puzzle (区间DP)

    ZOJ 3541 题目大意:有n个按钮,第i个按钮在按下ti 时间后回自动弹起,每个开关的位置是di,问什么策略按开关可以使所有的开关同时处于按下状态 Description There is one ...

随机推荐

  1. 2:spring中的@resource

    @Resource 其实是spring里面的注解注入. @Resource(这个注解属于J2EE的),默认安照名称进行装配,名称可以通过name属性进行指定, 如果没有指定name属性,当注解写在字段 ...

  2. std::async

    https://www.cnblogs.com/qicosmos/p/3534211.html https://bobjin.com/blog/c_cpp_docs/reference/en/cpp/ ...

  3. Tensorflow实战Google深度学习框架-总结-1

    第一章:深度学习简介   1⃣️应用有 1.计算机视觉 2.语音识别 3.自然语言处理 4.人机博弈   2⃣️深度学习,机器学习,AI 的关系

  4. python 常用模块之os

    1.权限判断 bool: os.access('/python/test.py',os.F_OK) #是否存在 bool: os.access('/python/test.py',os.R_OK) # ...

  5. P4889 kls与flag

    P4889 kls与flag 一堆杆子, 每个有特定高度 \(a_{i}\) , 现想把杆子弄倒, 可以在一维内往左弄倒和往右弄倒, 求最大优秀对数, 定义优秀对数为两杆倒后顶点重合 Solution ...

  6. python中的模块及路径

    python在import module的时候 是按照以下顺序去import一个module的: 1. 首先判断这个module是不是built-in即内建模块, 如果是则引入内建模块,如果不是则在一 ...

  7. Hadoop生态圈-phoenix(HBase)的索引配置

    Hadoop生态圈-phoenix(HBase)的索引配置 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 创建索引是为了优化查询,我们可以在phoenix上配置索引方式. 一.修改 ...

  8. Linux初学之vmware Workstation 网络连接三种模式

    简介: VM(VMware Workstation简称VM,后面都将用VM代替阐述)是一款功能强大的虚拟化软件.VM支持在 单一的桌面上同时运行多款不同的操作系统,能够模拟完整的网络环境,支持pxe功 ...

  9. C\C++中 fopen中文件打开方式的区别:

    在C语言中,大家常用到fopen打开文件,准备进行写操作,再用fwrite把数据写入文件,最后用fclose关闭文件. 如以下C代码:   #include <stdio.h> char ...

  10. Hi35xx 通用GPIO 使用篇(板子3G电源控制脚说明)

    在一个嵌入式系统中使用最多的莫过于 通用输入输出 GPIO口.看到论坛中经常有朋友问海思为什么没有提供GPIO驱动.其实不然. 在海思SDK  xxx/osdrv/tools/board_tools/ ...