题意:一块多边形,如果是凹多边形则直接输出“I can't cut.”,否则将他进行三角形剖分,每切一刀的花费是
|x1+x2|*|y1+y2|%p,x和y分别是点的坐标,问剖分的最小花费是多少
最优三角形剖分:对于一个n个顶点的凸多边形,可以用n-3条互不相交的对角线b把凸多边形分成n-2个三角形,
定义dp[i][j]为从顶点i到顶点j所构成的子凸多边形的最小三角剖分权值和,则边PiPj在此多边形内一定属于三角形PiPjPk,只要枚举k的位置,就能把多边形分割成2个子多边形,dp[i][j]=min(dp[i][k]+dp[k][j]+c[i][k]+c[k][j])
#include<bits/stdc++.h>
#define eps 1e-9
using namespace std;
const int MX = 305;
int sgn (double x) {
if (fabs (x) < eps) return 0;
if (x < 0) return -1;
else return 1;
}
struct Point {
double x, y;
Point (double xx, double yy) {
x = xx;
y = yy;
}
Point() {}
Point operator- (const Point& p) const {
return Point (x - p.x, y - p.y);
}
double operator^ (const Point& p) const {
return x * p.y - y * p.x;
}
double operator* (const Point& p) const {
return x * p.x + y * p.y;
}
} p[MX];
double dist (Point p1, Point p2) {
return sqrt ( (p1 - p2) * (p1 - p2));
}
bool cmp (Point p1, Point p2) {
double tmp = (p1 - p[0]) ^ (p2 - p[0]);
if (sgn (tmp) > 0) return true;
if (sgn (tmp) == 0 && sgn (dist (p1, p[0]) - dist (p2, p[0])) >= 0) return true;
return false;
}
bool ok (Point p1, Point p2, Point p3) {
double tmp = (p1 - p2) ^ (p1 - p3);
if (sgn (tmp) <= 0) return false;
return true;
}
int mod, n;
int dp[MX][MX],c[MX][MX];
int f(int i,int j){
int x1=p[i].x,x2=p[j].x,y1=p[i].y,y2=p[j].y;
return abs(x1+x2)*abs(y1+y2)%mod;
}
int main() {
while (~scanf ("%d%d", &n,&mod)) {
int k = 0;
for (int i = 0; i < n; i++) {
scanf ("%lf%lf", &p[i].x, &p[i].y);
if ( (p[k].y > p[i].y) || (p[k].y == p[i].y && p[k].x > p[i].x)) k = i;
}
swap (p[k], p[0]);
sort (p + 1, p + n, cmp);
bool flag = 1;
for (int i = 0; i < n; i++) {
if (!ok (p[i], p[ (i + 1) % n], p[ (i + 2) % n])) {
flag = 0;
break;
}
}
if (!flag) {
printf("I can't cut.\n");
continue;
}
memset(dp,0x3f,sizeof(dp));
memset(c,0,sizeof(c));
for(int i=0;i<n;i++)
for(int j=i+2;j<n;j++)
c[i][j]=c[j][i]=f(i,j);
for(int i=0;i<n;i++) dp[i][(i+1)%n]=0;
for(int l=2;l<n;l++){
for(int i=0;i+l<n;i++){
int j=i+l;
for(int k=i+1;k<j;k++){
dp[i][j]=min(dp[i][k]+dp[k][j]+c[i][k]+c[k][j],dp[i][j]);
}
}
}
printf("%d\n",dp[0][n-1]);
}
return 0;
}