这是一道区间dp的经典题目,定义状态为dp[i][j]为第i个切点到第j个切点的最小耗费,状态转移方程dp[i][j]=min{dp[i][k]+dp[k]][j]|i<k<j}.通过不断递归和记忆化搜索(减小重复),比较难理解,要多模拟过程才行。
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
const int MAX=99999999;
int dp[60][60],point[60];
int cut_point(int i,int j) //在切点i和j的位置进行切割
{
if(i==j-1) //如果是相邻的两个切点,不再切割,返回区间i到j的耗费
return dp[i][j];
if(dp[i][j]!=0) //减小重复工作
return dp[i][j];
dp[i][j]=MAX; //初始化为最大值
for(int k=i+1;k<j;k++) //k来枚举i到j之间的切点位置
{
dp[i][j]=min(dp[i][j],cut_point(i,k)+cut_point(k,j)+point[j]-point[i]);
}
return dp[i][j];
}
int main()
{
int l;
while(scanf("%d",&l)!=EOF&&l)
{
int n;
memset(dp,0,sizeof(dp));
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&point[i]);
}
point[0]=0; //将木棒两端也看做是切点,只不过是特殊的切点
point[n+1]=l;
printf("The minimum cutting is %d.\n",cut_point(0,n+1));
}
return 0;
}