题目链接: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])。
不懂的可以看下图(非原创):

代码:

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<vector>
  5. #include<cmath>
  6. #include<algorithm>
  7. using namespace std;
  8. const int INF=0x3f3f3f3f;
  9. const int N=;
  10. const double eps = 1e-;
  11.  
  12. int n,mod;
  13. int dp[N][N],cost[N][N];
  14.  
  15. struct P
  16. {
  17. double x, y;
  18. P(double x=, double y=):x(x), y(y) {}
  19. double add(double a, double b){
  20. if(fabs(a+b)<eps*(fabs(a)+fabs(b))) return ;
  21. return a+b;
  22. }
  23. P operator + (P p){
  24. return P(add(x, p.x), add(y, p.y));
  25. }
  26. P operator - (P p){
  27. return P(add(x, -p.x), add(y, -p.y));
  28. }
  29. P operator *(double d){
  30. return P(x*d, y*d);
  31. }
  32. double dot(P p){ //点积
  33. return add(x*p.x, y*p.y);
  34. }
  35. double det(P p){ //差积
  36. return add(x*p.y, -y*p.x);
  37. }
  38. }ps[N];
  39.  
  40. double dist(P a, P b){
  41. return sqrt((b-a).dot(b-a));
  42. }
  43.  
  44. bool cmp_x(const P& p, const P& q){
  45. if(p.x!=q.x) return p.x < q.x;
  46. return p.y < q.y;
  47. }
  48.  
  49. vector<P> convex_hull(P *ps, int n){
  50. sort(ps,ps+n,cmp_x);
  51. int k = ; //凸包顶点数
  52. vector<P> qs(n*);
  53. //构造凸包的下侧
  54. for(int i=; i<n; i++)
  55. {
  56. while(k> && (qs[k-]-qs[k-]).det(ps[i]-qs[k-])<=) k--;
  57. qs[k++] = ps[i];
  58. }
  59. //构造凸包的上侧
  60. for(int i=n-,t=k; i>=; i--)
  61. {
  62. while(k>t && (qs[k-]-qs[k-]).det(ps[i]-qs[k-])<=) k--;
  63. qs[k++] = ps[i];
  64. }
  65. qs.resize(k-);
  66. return qs;
  67. }
  68.  
  69. int getcost(P p1,P p2){
  70. return abs((int)p1.x+(int)p2.x)*abs((int)p1.y+(int)p2.y)%mod;
  71. }
  72.  
  73. int main(){
  74. while(~scanf("%d%d",&n,&mod)){
  75. for(int i=;i<n;i++){
  76. scanf("%lf%lf",&ps[i].x,&ps[i].y);
  77. }
  78. vector<P>tp;
  79. tp=convex_hull(ps,n);
  80. if(tp.size()<n){
  81. puts("I can't cut.");
  82. continue;
  83. }
  84. //注意,用获得的凸包做DP,即使用tp做DP,保证凸包上的点的顺序
  85. memset(cost,,sizeof(cost));
  86. memset(dp,,sizeof(dp));
  87. for(int i=;i<n;i++){
  88. for(int j=i+;j<n;j++){
  89. cost[i][j]=getcost(tp[i],tp[j]);
  90. }
  91. }
  92. for(int len=;len<n;len++){
  93. for(int i=;i+len<n;i++){
  94. int j=i+len;
  95. dp[i][j]=INF;
  96. for(int k=i+;k<=j-;k++){
  97. dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j]+cost[i][k]+cost[k][j]);
  98. }
  99. }
  100. }
  101. printf("%d\n",dp[][n-]);
  102. }
  103. return ;
  104. }

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. bzoj 3611: [Heoi2014]大工程 && bzoj 2286: [Sdoi2011消耗战

    放波建虚树的模板. 大概是用一个栈维护根节点到当前关键点的一条链,把其他深度大于lca的都弹出去. 每次做完记得复原. 还有sort的时候一定要加cmp!!! bzoj 3611 #include&l ...

  2. [NOI2011]阿狸的打字机——AC自动机之fail树的利用

    Description 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母. 经阿狸研究发现,这个打字机是这样工作的 ...

  3. 数据库之SQLite的介绍与使用20180705

    一.SQLite 简介 1.介绍 SQLite,是一款轻型的数据库,是遵守ACID的关系型数据库管理系统,它包含在一个相对小的C库中.它是D.RichardHipp建立的公有领域项目.它的设计目标是嵌 ...

  4. Framingham风险评估

    Framingham风险评分: Framingham 心脏研究和其他流行病学队列研究改变了20世纪后半部分对疾病的关注点,即从治疗已经存在的心血管疾病到预防处于疾病危险的状态.该策略的关键因素是识别那 ...

  5. HOJ 13101 The Triangle Division of the Convex Polygon(数论求卡特兰数(模不为素数))

    The Triangle Division of the Convex Polygon 题意:求 n 凸多边形可以有多少种方法分解成不相交的三角形,最后值模 m. 思路:卡特兰数的例子,只是模 m 让 ...

  6. CSS之float样式

    一.简介 Css样式的float浮动属性,用于设置标签对象(如:<div>标签盒子.<span>标签.<a>标签.<em>标签等html标签)的浮动布局 ...

  7. Zabbix应用二:Zabbix添加监控主机

    Zabbix添加被监控主机 一.选择中文语言 Zabbox3.0默认支持中文,可以登录后,点击右上角的用户图标,然后在语言中选择中文即可. 二.添加被监控主机 1.选择'配置'->'主机',然后 ...

  8. Hadoop基础-Apache Avro串行化的与反串行化

    Hadoop基础-Apache Avro串行化的与反串行化 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Apache Avro简介 1>.Apache Avro的来源 ...

  9. vue中的slot与slot-scope

    深入理解vue中的slot与slot-scope vue+element-ui+slot-scope或原生实现可编辑表格 vue插槽详解

  10. 2017 清北济南考前刷题Day 1 afternoon

    期望得分:80+30+70=180 实际得分:10+30+70=110 T1 水题(water) Time Limit:1000ms   Memory Limit:128MB 题目描述 LYK出了道水 ...