下面是别人的解题报告的链接,讲解很详细,要注意细节的处理。。。以及为什么可以这样做
http://blog.csdn.net/woshi250hua/article/details/7824433
我的代码:
1 //其中求凸包用的是Andrew扫描算法,复杂度主要为排序O(n*logn),扫描为O(n) 2 #include <cstdio> 3 #include <algorithm> 4 #define INF 100000000 5 #define min(a,b) a<b?a:b; 6 using namespace std; 7 //点的定义 8 struct point 9 { 10 int x,y; 11 bool operator <(const point & other) const 12 { 13 if(x == other.x) return y < other.y; 14 return x < other.x; 15 }; 16 } convex[330]; 17 //判断是往左还是往右 18 bool checkDir(point p0,point p1,point p2) 19 { 20 //往左返回true 21 if((p1.x-p0.x)*(p2.y-p0.y)-(p1.y-p0.y) * (p2.x-p0.x) <= 0) 22 return true; 23 else return false; 24 } 25 //求凸包的算法···,返回凸包的顶点数,输入的顶点数>=3。0,1,2特判,如果有需要的话 26 int andrew(point p[],int n) 27 { 28 sort(p,p+n); 29 int m=0; 30 for(int i=0; i<n; ++i) 31 { 32 while(m > 1 && checkDir(convex[m-2],convex[m-1],p[i]) ) --m; 33 convex[m++] = p[i]; 34 } 35 int k =m; 36 for(int i=n-2; i>=0; --i) 37 { 38 while(m > k && checkDir(convex[m-2],convex[m-1],p[i]) ) --m; 39 convex[m++] = p[i]; 40 } 41 return m-1; 42 } 43 int main() 44 { 45 // freopen("in.cpp","r",stdin); 46 int n,m,dp[330][330],cost[330][330]; 47 struct point p[330]; 48 while(scanf("%d%d",&n,&m) != EOF) 49 { 50 //读入数据 51 for(int i=0; i<n; ++i) 52 scanf("%d%d",&p[i].x,&p[i].y); 53 int num = andrew(p,n); 54 if(num != n) 55 { 56 printf("I can't cut. "); 57 continue; 58 } 59 //预处理dp数组的值 60 for(int i=0; i<n; ++i) 61 { 62 for(int j=0; j<n; ++j) 63 dp[i][j] = INF; 64 dp[i][(i+1)%n] = 0; 65 } 66 //预处理cost数组的值 67 for(int i=0; i<n; ++i) 68 { 69 cost[i][i+1] = cost[i+1][i] = 0; 70 cost[i][i] =0; 71 } 72 for(int i=0; i<n; ++i) 73 for(int j=i+2; j<n; ++j) 74 cost[j][i] = cost[i][j] = abs(convex[i].x + convex[j].x) * abs(convex[i].y+convex[j].y)%m; 75 //DP 76 for(int i=n-3; i>=0; --i) 77 for(int j=i+2; j<n; ++j) 78 for(int k=i+1; k < j; ++k) 79 dp[i][j] = min(dp[i][j],dp[i][k]+dp[k][j]+cost[k][i]+cost[k][j]); 80 printf("%d ",dp[0][n-1]); 81 } 82 return 0; 83 }