题意: 给一根长l的木棍(l<1000),给定木棍上的n个点(n<50),要求每个点处一刀,将木棍分成n+1部分,
每次划分时,花费=当前木棍长度,
怎么分才能使花费最小,输出最小花费?
题解: 给一根木棍,在中间允许的点上任意找一个分成两半,然后就形成2个更小的区间部分了,所以容易想到用区间dp来做。
将边界0和l加入,一共n+2个点,将各个点离散化,预处理处任意2点之间的长度,dp[i][j]表示以点i,j为边界的木棍最小花费,
转移方程为dp[i][j] = min(cost[i][j] + dp[i][k] + dp[k][j]) (i<k<j)
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define MAXN 55
#define INF 100000000
using namespace std;
int l,n;
int p[MAXN];
int dp[MAXN][MAXN];
int cost[MAXN][MAXN];
int main() {
while(scanf("%d",&l) != EOF && l) {
memset(cost,0,sizeof(cost));
memset(dp,0,sizeof(dp));
scanf("%d",&n);
p[0] = 0;
p[n+1] = l;
for(int i = 1;i <= n;i++) scanf("%d",&p[i]);
for(int i = 0;i <= n+1;i++)
for(int j = i+1;j <= n+1;j++) {
cost[i][j] = cost[j][i] = abs(p[i]-p[j]);
}
for(int len = 2;len <= n+1;len++)
for(int i = 0;i < n+1;i++) {
// i and j are both the array bounds
int j = i+len;
if(j > n+1) continue;
int t = INF;
// enumerate all cuts
for(int k = i+1;k < j;k++) {
t = min(t,cost[i][j]+dp[i][k]+dp[k][j]);
}
if(t == INF) dp[i][j] = 0;
else dp[i][j] = t;
}
printf("The minimum cutting is %d.\n",dp[0][n+1]);
}
return 0;
}