这道题是区间DP的经典题目。
题意:给你一根木棍,m个切割点。按顺序选切割点把木棍切开,每次切割的花费是这个木棍被切前的长度,求最小的花费。
设dp[i][j]表示从i到j的最小花费,那么dp[i][j]=min{dp[i][k]+dp[k][j]+a[j]-[i]}(i<k<j)
其中a[j]-a[i]表示从i到j的长度,即要切这块木条所需的花费。求大区间得时候小区间已经算出来了,所以符合动态规划的自底向上,而且是最优子结构,这道题我把0和木条长度加到了a数组里面,就是说一共有n+2个点,每两个相邻的点不用切割,初始化为1。
代码如下:
#include <bits/stdc++.h> #define ll long long using namespace std; const int maxn=400010; const int mo=1e9+7; int dp[60][60]; int a[60]; int cnt,tmp,ans; int k,l; int main() { int n,m,T,cas; while(scanf("%d",&l)!=EOF&&l) { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); } a[0]=0; a[n+1]=l; m=n+1; for(int i=0;i<m;i++) dp[i][i+1]=0; memset(dp,0,sizeof(dp)); for(int p=2;p<=m;p++)//length { for(int i=0;i<=m+1-p;i++)//start { int j=i+p; int mi=mo; for(int k=i+1;k<j;k++) { tmp=dp[i][k]+dp[k][j]+a[j]-a[i]; if(tmp<mi) mi=tmp; } if(mi!=mo) dp[i][j]=mi; } } printf("The minimum cutting is %d.\n",dp[0][m]); } return 0; }
附:
1 区间DP
2 区间动态规划问题一般都是考虑,对于每段区间,他们的最优值都是由几段更小区间的最优值得到。将一个区间问题不断划分为更小的区间直至一个元素组成的区间,枚举他们的组合,求合并后的最优值。
3 设F[i,j](1<=i<=j<=n)表示区间[i,j]内的数字相加的最小代价 , 最小区间F[i,i]=0(一个数字无法合并,∴代价为0)每次用变量k(i<=k<=j-1)将区间分为[i,k]和[k+1,j]两段
4《区间DP模板,代码》
for(intp = 1 ; p <= n ; p++){//p是区间的长度,作为阶段
for(int i = 1 ; i <= n ; i++)
{//i是穷举区间的起点
int j = i+p-1;//j为区间的终点
for(int k = i ; k < j ; k++)//状态转移
dp[i][j] = min{dp[i][k]+dp[k+1][j]+w[i][j]};
//这个是看题目意思,有的是要从k开始不是k+1
dp[i][j]= max{dp[i][k]+dp[k+1][j]+w[i][j]};
}
}