UVa 10003 - Cutting Sticks(区间DP)

链接:

https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=944

 

题意:

有一根长度为L(L<1000)的棍子,还有n(n<50)个切割点的位置(按照从小到大排列)。
你的任务是在这些切割点的位置处把棍子切成n+1部分,使得总切割费用最小(每次切割的费用等于被切割的木棍长度)。

 

分析:

设d(i,j)为切割小木棍第i点到第j点的最优费用,则d(i,j) = min{d(i,k) + d(k,j) | i<k<j} + a[j]-a[i],
其中最后一项a[j]-a[i]代表第一刀的费用。切完之后,小木棍变成i~k和k~j两部分,状态转移方程由此可得。
把切割点编号为1~n,左边界编号为0,右边界编号为n+1,则答案为d(0,n+1)。

 

代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 
 6 int a[50+5], d[50+5][50+5]; // d[i][j]为切割小木棍第i点到第j点的最优费用
 7 
 8 int dp(int L, int R){
 9     if(d[L][R] || L + 1 == R) return d[L][R];
10     int v = 12345;
11     for(int M = L + 1; M < R; M++) v = min(v, dp(L, M) + dp(M, R));
12     return d[L][R] = v + a[R] - a[L];
13 }
14 
15 int main(){
16     int L, n;
17     while(scanf("%d", &L) && L){
18         scanf("%d", &n);
19         for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
20         a[n+1] = L;
21         memset(d, 0, sizeof(d));
22         printf("The minimum cutting is %d.\n", dp(0, n + 1));
23     }
24     return 0;
25 }

 

posted @ 2018-03-19 13:57  Ctfes  阅读(163)  评论(0编辑  收藏  举报