UVa 10003 Cutting Sticks dp : 线性dp triangulation三角剖分

UVA - 10003
Cutting Sticks
Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu

Submit Status


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;
}




你可能感兴趣的:(ACM,uva,三角剖分,线性dp)