zoj 3537 区间dp+计算几何
题意:给定n个点的坐标,先问这些点是否能组成一个凸包,如果是凸包,问用不相交的线来切这个凸包使得凸包只由三角形组成,根据costi, j = |xi + xj| * |yi + yj| % p算切线的费用,问最少的切割费用。
链接:点我
题解:点我
2015-07-20:专题复习
代码稍微修改了一下,顺便发现题号写错了
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<queue> 7 #include<map> 8 using namespace std; 9 #define MOD 1000000007 10 const int INF=0x3f3f3f3f; 11 const double eps=1e-5; 12 typedef long long ll; 13 #define cl(a) memset(a,0,sizeof(a)) 14 #define ts printf("*****\n"); 15 const int MAXN=310; 16 int n,m; 17 int sgn(double x) 18 { 19 if(fabs(x) < eps)return 0; 20 if(x < 0)return -1; 21 else return 1; 22 } 23 struct Point 24 { 25 int x,y; 26 Point(){} 27 Point(double _x,double _y) 28 { 29 x = _x;y = _y; 30 } 31 Point operator -(const Point &b)const 32 { 33 return Point(x - b.x,y - b.y); 34 } 35 //叉积 36 double operator ^(const Point &b)const 37 { 38 return x*b.y - y*b.x; 39 } 40 //点积 41 double operator *(const Point &b)const 42 { 43 return x*b.x + y*b.y; 44 } 45 //绕原点旋转角度B(弧度值),后x,y的变化 46 }; 47 Point list[MAXN]; 48 int Stack[MAXN],top; 49 double dist(Point a,Point b) 50 { 51 return sqrt((a-b)*(a-b)); 52 } 53 //相对于list[0]的极角排序 54 bool _cmp(Point p1,Point p2) 55 { 56 double tmp=(p1-list[0])^(p2-list[0]); 57 if(sgn(tmp)>0)return true; 58 else if(sgn(tmp)==0 && sgn(dist(p1,list[0]) - dist(p2,list[0])) <= 0) 59 return true; 60 else return false; 61 } 62 void Graham(int n) 63 { 64 Point p0; 65 int k=0; 66 p0=list[0]; 67 //找最下边的一个点 68 for(int i=1;i < n;i++) 69 { 70 if( (p0.y>list[i].y) || (p0.y==list[i].y && p0.x>list[i].x) ) 71 { 72 p0=list[i]; 73 k=i; 74 } 75 } 76 swap(list[k],list[0]); 77 sort(list+1,list+n,_cmp); 78 if(n==1) 79 { 80 top=1; 81 Stack[0]=0; 82 return; 83 } 84 if(n==2) 85 { 86 top=2; 87 Stack[0]=0; 88 Stack[1]=1; 89 return ; 90 } 91 Stack[0]=0; 92 Stack[1]=1; 93 top=2; 94 for(int i=2;i < n;i++) 95 { 96 while(top>1 && sgn((list[Stack[top-1]]-list[Stack[top-2]])^(list[i]-list[Stack[top-2]])) <= 0) 97 top--; 98 Stack[top++]=i; 99 } 100 } 101 int cost[MAXN][MAXN]; 102 int dis(Point p1,Point p2)//计算题目定义的cost 103 { 104 return abs(p1.x+p2.x)*abs(p1.y+p2.y)%m; 105 } 106 int dp[MAXN][MAXN]; 107 int main() 108 { 109 int i,j,k; 110 #ifndef ONLINE_JUDGE 111 freopen("1.in","r",stdin); 112 #endif 113 while(~scanf("%d%d",&n,&m)) 114 { 115 for(i=0;i<n;i++) 116 { 117 scanf("%d%d",&list[i].x,&list[i].y); 118 } 119 Graham(n); 120 if(top!=n) 121 { 122 puts("I can't cut."); 123 continue; 124 } 125 cl(cost); 126 for(i=0;i<n;i++) 127 for(j=i+2;j<n;j++) 128 cost[i][j]=cost[j][i]=dis(list[i],list[j]); 129 for(i=0;i<n;i++) 130 { 131 for(j=i;j<n;j++)dp[i][j]=INF; 132 dp[i][(i+1)%n]=0; 133 } 134 for(int len=2;len<n;len++) 135 { 136 for(i=0;i+len<=n-1;i++) 137 { 138 j=i+len; 139 for(k=i+1;k<=j-1;k++) 140 { 141 dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j]+cost[i][k]+cost[k][j]); 142 } 143 } 144 } 145 /*for(i=n-3;i>=0;i--) 146 { 147 for(j=i+2;j<n;j++) 148 { 149 for(k=i+1;k<=j-1;k++) 150 { 151 dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j]+cost[i][k]+cost[k][j]); 152 } 153 } 154 }*/ 155 printf("%d\n",dp[0][n-1]); 156 } 157 }
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<queue> 7 #include<map> 8 using namespace std; 9 #define MOD 1000000007 10 const int INF=0x3f3f3f3f; 11 const double eps=1e-5; 12 typedef long long ll; 13 #define cl(a) memset(a,0,sizeof(a)) 14 #define ts printf("*****\n"); 15 const int MAXN=310; 16 int n,m; 17 int sgn(double x) 18 { 19 if(fabs(x) < eps)return 0; 20 if(x < 0)return -1; 21 else return 1; 22 } 23 struct Point 24 { 25 int x,y; 26 Point(){} 27 Point(double _x,double _y) 28 { 29 x = _x;y = _y; 30 } 31 Point operator -(const Point &b)const 32 { 33 return Point(x - b.x,y - b.y); 34 } 35 //叉积 36 double operator ^(const Point &b)const 37 { 38 return x*b.y - y*b.x; 39 } 40 //点积 41 double operator *(const Point &b)const 42 { 43 return x*b.x + y*b.y; 44 } 45 //绕原点旋转角度B(弧度值),后x,y的变化 46 }; 47 Point list[MAXN]; 48 int Stack[MAXN],top; 49 double dist(Point a,Point b) 50 { 51 return sqrt((a-b)*(a-b)); 52 } 53 //相对于list[0]的极角排序 54 bool _cmp(Point p1,Point p2) 55 { 56 double tmp=(p1-list[0])^(p2-list[0]); 57 if(sgn(tmp)>0)return true; 58 else if(sgn(tmp)==0 && sgn(dist(p1,list[0]) - dist(p2,list[0])) <= 0) 59 return true; 60 else return false; 61 } 62 void Graham(int n) 63 { 64 Point p0; 65 int k=0; 66 p0=list[0]; 67 //找最下边的一个点 68 for(int i=1;i < n;i++) 69 { 70 if( (p0.y>list[i].y) || (p0.y==list[i].y && p0.x>list[i].x) ) 71 { 72 p0=list[i]; 73 k=i; 74 } 75 } 76 swap(list[k],list[0]); 77 sort(list+1,list+n,_cmp); 78 if(n==1) 79 { 80 top=1; 81 Stack[0]=0; 82 return; 83 } 84 if(n==2) 85 { 86 top=2; 87 Stack[0]=0; 88 Stack[1]=1; 89 return ; 90 } 91 Stack[0]=0; 92 Stack[1]=1; 93 top=2; 94 for(int i=2;i < n;i++) 95 { 96 while(top>1 && sgn((list[Stack[top-1]]-list[Stack[top-2]])^(list[i]-list[Stack[top-2]])) <= 0) 97 top--; 98 Stack[top++]=i; 99 } 100 } 101 int cost[MAXN][MAXN]; 102 int dis(Point p1,Point p2)//计算题目定义的cost 103 { 104 return abs(p1.x+p2.x)*abs(p1.y+p2.y)%m; 105 } 106 int dp[MAXN][MAXN]; 107 int main() 108 { 109 int i,j,k; 110 #ifndef ONLINE_JUDGE 111 freopen("1.in","r",stdin); 112 #endif 113 while(~scanf("%d%d",&n,&m)) 114 { 115 for(i=0;i<n;i++) 116 { 117 scanf("%d%d",&list[i].x,&list[i].y); 118 } 119 Graham(n); 120 if(top!=n) 121 { 122 puts("I can't cut."); 123 continue; 124 } 125 cl(cost); 126 for(i=0;i<n;i++) 127 for(j=i+2;j<n;j++) 128 cost[i][j]=cost[j][i]=dis(list[i],list[j]); 129 for(i=0;i<n;i++) 130 { 131 for(j=i;j<n;j++)dp[i][j]=INF; 132 dp[i][(i+1)%n]=0; 133 } 134 for(i=n-3;i>=0;i--) 135 { 136 for(j=i+2;j<n;j++) 137 { 138 for(k=i+1;k<=j-1;k++) 139 { 140 dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j]+cost[i][k]+cost[k][j]); 141 } 142 } 143 } 144 printf("%d\n",dp[0][n-1]); 145 } 146 }