码迷,mamicode.com
首页 > 其他好文 > 详细

10003 - Cutting Sticks(DP)

时间:2015-07-12 14:21:36      阅读:226      评论:0      收藏:0      [点我收藏+]

标签:acm   uva   

类似于最优矩阵链乘,将长区间划分成段区间求解,换句话说:长区间依赖于段区间 。 因此如果利用二重循环递推的话,枚举的顺序应该是木棍的长度从小到大,因为长区间依赖于短区间的最优解 。 所以动态规划的重点我认为就是对状态的定义和动态规划的方向,  状态的定义要确保覆盖所有状态,规划的方向要遵循一个状态依赖于另一个早已解决的状态。     所以该题有两种解决方法:记忆化搜索和递推 。

我分别用这两种方法AC了,记忆化搜索更简单易想,耗时0.339。但是递推更快!耗时0.086 。细节请见代码:

1.记忆化搜索:

#include<bits/stdc++.h>
using namespace std;
const int INF = 2000000000;
int n,l,a[55],d[55][55];
int dp(int i,int j) {
    int& ans = d[i][j];
    if(ans!=-1) return ans;
    ans = INF;
    for(int k=i+1;k<j;k++) {
        ans = min(ans,dp(i,k) + dp(k,j) + a[j] - a[i]);
    }
    return ans;
}
int main() {
    while(~scanf("%d",&l)&&l) {
        scanf("%d",&n);
        memset(d,-1,sizeof(d));//初始化特殊值
        for(int i=0;i<=n;i++) d[i][i+1] = 0; //初始化边界
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        a[n+1] = l; a[0] = 0;
        printf("The minimum cutting is %d.\n",dp(0,n+1));
    }
    return 0;
}

2.递推:

#include<bits/stdc++.h>
using namespace std;
const int INF = 2000000000;
int n,l,a[55],d[55][55];
int main() {
    while(~scanf("%d",&l)&&l) {
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        a[n+1] = l; a[0] = 0;
        for(int len=1;len<=n+1;len++) { //按照木棍长度从小到大递推
            for(int i=0;i<=n;i++) {//i + len 就是j
                if(i+len > n+1) break;
                d[i][i+len] = (len == 1 ? 0 : INF);
                for(int k=i+1;k<i+len;k++) { //寻找切割点
                    d[i][i+len] = min(d[i][i+len],d[i][k] + d[k][i+len] + a[i+len] - a[i]);
                }
            }
        }
        printf("The minimum cutting is %d.\n",d[0][n+1]);
    }
    return 0;
}



版权声明:本文为博主原创文章,未经博主允许不得转载。

10003 - Cutting Sticks(DP)

标签:acm   uva   

原文地址:http://blog.csdn.net/weizhuwyzc000/article/details/46848951

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!