题目
思路
1.状态定义:d(i,j),切割位于切割点i和j之间的木棍需要的最小费用。
2.初状态:d(i,i+1) = 0,A[0] = 0, A[n+1] = L
3.答案:d(0,n+1)
4.状态转移方程:
5.复杂度:
1.注意本题的边界处理,很巧妙
2.本题其实根据切割点来进行DP,特别是A[j]-A[i]这个操作,很厉害的离散化。数据量从1000降到了50。
代码
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#define _for(i,a,b) for(int i = (a); i<(b); i++)
#define _rep(i,a,b) for(int i = (a); i<=(b); i++)
using namespace std;
const int INF = 100000;
const int maxn = 50 + 5;
int n, L, A[maxn], d[maxn][maxn];
int main() {
while (scanf("%d", &L) == 1 && L) {
scanf("%d", &n);
_rep(i, 1, n) scanf("%d", &A[i]);
A[0] = 0;
A[n + 1] = L;
// _rep(i,0,n) d[i][i+1] = 0;
int j;
_rep(l,2,n+1)
_rep(i, 0, n) {
j = i + l;
if (j > n + 1) continue;
d[i][j] = INF;
_rep(k, i + 1, j - 1)
d[i][j] = min(d[i][j], d[i][k] + d[k][j] + A[j] - A[i]);
}
printf("The minimum cutting is %d.\n", d[0][n + 1]);
}
return 0;
}