题目大意
有一根长度为L的木根,还有n个切割的起点(按照从小到大的顺序排列),你的任务是在这些切割点的位置将木根切成n+1部分,使得总切割费用最小。
每次切割的费用等于被切割的木根的长度。
思路
设dp[i][j]为切割木根i~j的最优费用,则
dp[i][j] = min{dp[i][k] + dp[k][j]|i<k<j} + a[j] - a[i];
a[j] - a[i]
代表了第一刀的花费,则dp的起点是dp[i][i+1] = 0
.
代码
#include<stdio.h>
#include<cstring>
#include<set>
#define maxn 55
#define INF 1<<30
#define min(a,b) (a>b)? b:a
#define max(a,b) (a>b)? a:b
using namespace std;
int a[maxn];
int dp[maxn][maxn];
int main ()
{
int L,n;
while(1)
{
scanf("%d",&L);
if(L==0) break;
scanf("%d",&n);
for(int i = 1; i<=n; i++) scanf("%d",&a[i]);
a[0] = 0;
a[n+1] = L;
for(int i = 0; i<=n; i++) dp[i][i+1] = 0;
for(int i = n-1; i>=0; i--)
{
for(int j = i+2; j<=n+1; j++)
{
int tmp = INF;
for(int k = i + 1; k < j; k++)
{
tmp = min(tmp,dp[i][k]+dp[k][j]+a[j]-a[i]);
}
dp[i][j] = tmp;
}
}
printf("The minimum cutting is %d.\n",dp[0][n+1]);
}
}
/*
Sample Input
100
3
25 50 75
10
4
4 5 7 8
0
Sample Output
The minimum cutting is 200.
The minimum cutting is 22.
*/
Hit
注意dp过程中i和j的顺序,在计算当前状态的时候,使用的先前状态是否被计算出来。