zoj 3537 Cake 区间DP (好题)

题意:切一个凸边行,如果不是凸包直接输出。然后输出最小代价的切割费用,把凸包都切割成三角形。

先判断是否是凸包,然后用三角形优化。

dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j]+w[i][k]+w[j][k]);

w[i][j]代表i到j点的切割费用。

dp[i][j]:表示以i到j点的最小费用。则可把凸边行分成三个部分的费用。两个凸边行(i,k),(k,j)和两条边的费用(i,k),(j,k),k为枚举的三角形顶点。

Zoj 3537 Cake (DP_最优三角形剖分)

  1 //#pragma comment(linker, "/STACK:167772160")//手动扩栈~~~~hdu 用c++交
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<cstdlib>
  5 #include<iostream>
  6 #include<queue>
  7 #include<stack>
  8 #include<cmath>
  9 #include<set>
 10 #include<algorithm>
 11 #include<vector>
 12 // #include<malloc.h>
 13 using namespace std;
 14 #define clc(a,b) memset(a,b,sizeof(a))
 15 #define LL long long
 16 const int inf = 0x3f3f3f3f;
 17 const double eps = 1e-5;
 18 const double pi = acos(-1);
 19 // inline int r(){
 20 //     int x=0,f=1;char ch=getchar();
 21 //     while(ch>'9'||ch<'0'){if(ch=='-') f=-1;ch=getchar();}
 22 //     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
 23 //     return x*f;
 24 // }
 25 const int maxn=1010;
 26 struct Point{
 27     int x, y;
 28     Point(int x=0, int y=0):x(x),y(y) { }
 29 }p[maxn];
 30 
 31 // typedef Point Vector;
 32 
 33 int w[maxn][maxn],dp[maxn][maxn],n,m;
 34 
 35 // Vector operator + (const Vector& A, const Vector& B)
 36 // {
 37 //     return Vector(A.x+B.x, A.y+B.y);
 38 // }
 39 // Vector operator - (const Point& A, const Point& B)
 40 // {
 41 //     return Vector(A.x-B.x, A.y-B.y);
 42 // }
 43 // double Cross(const Vector& A, const Vector& B)
 44 // {
 45 //     return A.x*B.y - A.y*B.x;
 46 // }
 47 
 48 // Vector Rotate(const Vector& A, double rad)
 49 // {
 50 //     return Vector(A.x*cos(rad)-A.y*sin(rad), A.x*sin(rad)+A.y*cos(rad));
 51 // }
 52 
 53 // bool operator < (const Point& p1, const Point& p2)
 54 // {
 55 //     return p1.x < p2.x || (p1.x == p2.x && p1.y < p2.y);
 56 // }
 57 
 58 // bool operator == (const Point& p1, const Point& p2)
 59 // {
 60 //     return p1.x == p2.x && p1.y == p2.y;
 61 // }
 62 // // 点集凸包
 63 // // 如果不希望在凸包的边上有输入点,把两个 <= 改成 <
 64 // // 如果不介意点集被修改,可以改成传递引用
 65 // vector<Point> ConvexHull(vector<Point> p)
 66 // {
 67 //     // 预处理,删除重复点
 68 //     sort(p.begin(), p.end());
 69 //     p.erase(unique(p.begin(), p.end()), p.end());
 70 
 71 //     int n = p.size();
 72 //     int m = 0;
 73 //     vector<Point> ch(n+1);
 74 //     for(int i = 0; i < n; i++)
 75 //     {
 76 //         while(m > 1 && Cross(ch[m-1]-ch[m-2], p[i]-ch[m-2]) <= 0) m--;
 77 //         ch[m++] = p[i];
 78 //     }
 79 //     int k = m;
 80 //     for(int i = n-2; i >= 0; i--)
 81 //     {
 82 //         while(m > k && Cross(ch[m-1]-ch[m-2], p[i]-ch[m-2]) <= 0) m--;
 83 //         ch[m++] = p[i];
 84 //     }
 85 //     if(n > 1) m--;
 86 //     ch.resize(m);
 87 //     return ch;
 88 // }
 89 Point save[400],temp[400];  
 90 int xmult(Point p1,Point p2,Point p0){  
 91   
 92     return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);  
 93 }  
 94 bool cmp(const Point &a,const Point &b){  
 95   
 96     if(a.y == b.y)return a.x < b.x;  
 97     return a.y < b.y;  
 98 }  
 99 int Graham(Point *p,int n) {  
100     int i;  
101     sort(p,p + n,cmp);  
102     save[0] = p[0];  
103     save[1] = p[1];  
104     int top = 1;  
105     for(i = 0;i < n; i++){  
106   
107         while(top && xmult(save[top],p[i],save[top-1]) >= 0)top--;  
108         save[++top] = p[i];  
109     }  
110     int mid = top;  
111     for(i = n - 2; i >= 0; i--){  
112   
113         while(top>mid&&xmult(save[top],p[i],save[top-1])>=0)top--;  
114         save[++top]=p[i];  
115     }  
116     return top;  
117 }  
118 
119 int main(){
120     // freopen("in.txt","r",stdin);
121     while(~scanf("%d%d",&n,&m)){
122         for(int i=0;i<n;i++) scanf("%d%d",&p[i].x,&p[i].y);
123      clc(dp,0);
124      clc(w,0);
125      int v;
126      v=Graham(p,n);
127      // printf("%d
",(int)v.size()); 
128      if(v<n) printf("I can't cut.
");   
129      else{
130             for (int i = 0; i < n; ++i)  
131                 for (int j = i + 2; j < n; ++j)  
132                     w[i][j] = w[j][i] =(abs(save[i].x + save[j].x) * abs(save[i].y+save[j].y)) % m;
133             for (int i = 0; i < n; ++i) {  
134                 for (int j = 0; j < n; ++j)  
135                     dp[i][j] = inf;  
136                 dp[i][(i+1)%n] = 0;  
137             }  
138             for (int i = n - 3; i >= 0; --i) 
139                 for (int j = i + 2; j < n; ++j) 
140                     for (int k = i + 1; k <= j - 1; ++k)  
141                         dp[i][j] = min(dp[i][j],dp[i][k]+dp[k][j]+w[i][k]+w[k][j]);  
142             printf("%d
",dp[0][n-1]);  
143         }  
144     }
145     return 0;
146 }
View Code
原文地址:https://www.cnblogs.com/ITUPC/p/5477064.html