UVA - 10003
Cutting Sticks
|
The question is from here.
My Solution
线性dp 三角剖分类题目的经典吧,
状态:d[ i ][ j ] 表示切割 i - j 这一段的最小费用 ,0 <= i < j <= n+1,自己画个线段看看,切割位置为1-n。
转移:必然存在一个k,使得 i - k - j得到一个最小值,即 d[ i ][ j ] = min(d[ i ][ j ], d[ i ][ k ]+d[ k+1 ][ j ]; k的地方切一刀,这是里面的最小值
算完以后加上 a[ j ] - a[ i ]这额外的第一刀;
边界:d[i][i] = 0;
d[i][i+1] = 0;
其它的要用的时候初始化为INF; 最开始做的时候初始化为a[ j ] - a[ i ];结果算出的比答案的还要小一点,这样初始化当然是不对的下面有解释
带注释版
#include <iostream> #include <cstdio> //#define LOCAL using namespace std; int a[54],d[54][54]; const int INF = 0x3f3f3f3f; int main() { #ifdef LOCAL freopen("a.txt","r",stdin); #endif // LOCAL int l,n; while(scanf("%d", &l) && l != 0){ 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+1; i++){ d[i][i] = 0; d[i][i+1] = 0; //d[i][i+2] = a[i+2] - a[i]; } for(int i = n; i >= 0; i--){ //!注意顺序 for(int j = i+1; j <= n+1; j++){ if(i+1 != j) d[i][j] = INF; // d[i][j] 不一定比里面最小的一个大 因为再切一刀,里面可能还要切几次,如10 小于 6+3+3,比如说最后一次 // 所以前面用的 d[i][j] = a[j]-a[i];的初始化是完全不行的 for(int k = i; k < j; k++){ d[i][j] = min(d[i][j], d[i][k]+d[k][j]); } if(i+1 != j) d[i][j] += a[j]-a[i]; } } printf("The minimum cutting is %d.\n", d[0][n+1]); } return 0; }
简洁版
#include <iostream> #include <cstdio> using namespace std; int a[54],d[54][54],l,n; const int INF = 0x3f3f3f3f; int main() { while(scanf("%d", &l) && l != 0){ 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+1; i++){ d[i][i] = 0; d[i][i+1] = 0; } for(int i = n; i >= 0; i--){ for(int j = i+1; j <= n+1; j++){ if(i+1 != j) d[i][j] = INF; for(int k = i; k < j; k++) d[i][j] = min(d[i][j], d[i][k]+d[k][j]); if(i+1 != j) d[i][j] += a[j]-a[i]; } } printf("The minimum cutting is %d.\n", d[0][n+1]); } return 0; }