动态规划——切蛋糕

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();
}


你可能感兴趣的:(动态规划——切蛋糕)