题目链接
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4472
题目解析
题目中有一个蛋糕,要求尽可能的分割蛋糕,并且每一个对角线的切割都有一定的消费,要求计算消费最小,并且如果这个多边形不满足凸包,直接输出"I can't cut."
题目相对于最优三角划分,只是多了一个凸包的判断,并且这也就是一个模板题目,可以直接使用Graham扫描法的模板计算,然后如果是凸包,那么再去计算最优的划分消耗
#include <iostream> #include <cstdio> #include <cmath> #include <cstring> #include <algorithm> #include <math.h> #include <queue> #define INF 0x3f3f3f3f using namespace std; const int MAXN = 350; int n,m; struct Point { int x,y; }p[MAXN],c[MAXN]; int cost[MAXN][MAXN],dp[MAXN][MAXN]; int mulit(Point p0, Point p1, Point p2) { return (p1.x - p0.x) * (p2.y - p0.y) - (p2.x - p0.x) * ( p1.y - p0.y); } double dis(Point a,Point b) { return (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y); } bool cmp(Point a,Point b) { int x = mulit(p[0],a,b); if(x > 0 || (x == 0 && dis(p[0],a) < dis(p[0],b))) return true; return false; } int Get_cost(Point a,Point b) { return abs(a.x + b.x) * abs(a.y + b.y) % m; } int Graham() { if(n == 1) return 0; int k = 0; for(int i = 1;i < n;i ++) if(p[i].y < p[k].y || (p[i].y == p[k].y && p[i].x < p[k].x)) k = i; swap(p[0],p[k]); sort(p+1,p+n,cmp); c[0] = p[0];c[1] = p[1];int tot = 1; for(int i = 2;i < n;i ++) { while(tot && mulit(c[tot-1],c[tot],p[i]) <= 0) tot--; c[++tot] = p[i]; } return tot; } int main() { while(~scanf("%d%d",&n,&m)) { memset(cost,0,sizeof(cost)); memset(dp,0,sizeof(dp)); for(int i = 0 ;i < n;i ++) scanf("%d%d",&p[i].x,&p[i].y); if(Graham() != n-1) printf("I can't cut.\n"); else { for(int i = 0;i < n;i ++) for(int j = i+2;j < n;j ++) cost[i][j] = cost[j][i] = Get_cost(p[i],p[j]); for(int i = n-3;i >= 0;i --) for(int j = i+2;j < n;j ++) { dp[i][j] = INF; for(int k = i+1;k < j;k ++) dp[i][j] = min(dp[i][j],cost[i][k] + cost[j][k] + dp[i][k] + dp[k][j]); } printf("%d\n",dp[0][n-1]); } } return 0; }