nkoj 2305 改编自ZOJ3537
Description
有一个凸多边形蛋糕,你现在要用刀把它切成若干块三角形的小蛋糕。每一刀你只能沿着当前凸多边形的某条对角线切。我们可以把蛋糕看成是笛卡尔坐标系中的n个坐标点连接而成的图形,每次切割都会消耗一定的体力,切割第i和第j号点构成的对角线所消耗的体力为cost(i,j)=|xi+xj|*|yi+yj| mod t,t为题目给出的体力常数。
问,怎样切割才能使得耗费的体力最少,求出这个最少耗费的体力
代码如下:
#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
long long n,t,w[605][605],f[605][605];
/* f[i][j]表示从第i个顶点到第j个顶点的最小体力消耗;
w[i][j]表示沿i,j切一刀的体力消耗 */
struct point{
long long x,y;
}s[605];
void input(){
int i,j;
scanf("%I64d%I64d",&n,&t);
for(i=1;i<=n;i++)
scanf("%I64d%I64d",&s[i].x,&s[i].y);
for(i=1;i<=n;i++)
for(j=i+2;j<=n;j++)
w[i][j]=w[j][i]=(abs(s[i].x+s[j].x)*abs(s[i].y+s[j].y))%t;
}
void solve(){
int i,j,x,k;
for(i=1;i<=n;i++){
for(j=1;j<=n;j++)
f[i][j]=99999999999999999LL;
f[i][i+1]=0; // 相邻的点
}
f[n][1]=0; //特殊处理
for (i=n-2;i>0;i--) //要保证f[k][j]已经计算出来,所以逆序
for (j=i+2;j<=n;j++) // 要保证f[k][j]已经算出,所以要顺序
for(k=i+1;k<j;k++)
f[i][j]=min(f[i][j],f[i][k]+f[k][j]+w[i][k]+w[k][j]);
printf("%I64d",f[1][n]);
}
int main(){
input();
solve();
}