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

来源:互联网 发布:数据库人事管理系统 编辑:程序博客网 时间:2024/06/10 07:25

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




0 0
原创粉丝点击