动态规划练习——UVa10003——区间dp

题目链接:https://vjudge.net/contest/232313#problem/I

紫书上的动态规划例题,很明显是一个区间线性规划的问题,想起之前做过的矩阵链乘,这题和它很像,枚举方向都是向j-i递增的

方向,这里有个大神的区间dp模板的总结:http://www.cnblogs.com/zsboy/archive/2013/03/08/2950261.html可以强化理解。

所以,设dp[i][j]为切割小木棍i~j点的费用,则dp[i][j]=min{dp[i][k]+dp[k][j]+a[j]-a[i]},a[j]-a[i]表示第一刀切割为i~j的费用,而

dp[i][k]和dp[k][j]就像最优矩阵链乘一样,将问题分割为了两个子问题,所以长区间必须由短区间推得,和紫书上的思路一样。

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;

const int maxn=55;
int a[maxn];
int dp[maxn][maxn];
const int INF=0x3f3f3f3f;

int main()
{
    int l;
    while(scanf("%d",&l)!=EOF)
    {
        if(l==0)break;
        int n;
        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++)
            dp[i][i+1]=0;
        for(int x=1;x<=n+1;x++)//区间长度
        {
            for(int i=0;i<=n+1;i++)//起点
            {
                int j=i+x;//终点
                if(j>n+1)break;
                int minn=INF;
                for(int k=i+1;k<j;k++)
                {
                    int temp=dp[i][k]+dp[k][j]+a[j]-a[i];
                    minn=min(minn,temp);
                }
                if(minn!=INF)
                    dp[i][j]=minn;
            }
        }
        printf("The minimum cutting is %d.\n",dp[0][n+1]);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Q755100802/article/details/83040240