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\n",(int)v.size()); 128 if(v<n) printf("I can't cut.\n"); 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\n",dp[0][n-1]); 143 } 144 } 145 return 0; 146 }