UVA - 10003 Cutting Sticks(经典区间DP)

这道题是区间DP的经典题目。

题意:给你一根木棍,m个切割点。按顺序选切割点把木棍切开,每次切割的花费是这个木棍被切前的长度,求最小的花费。

设dp[i][j]表示从i到j的最小花费,那么dp[i][j]=min{dp[i][k]+dp[k][j]+a[j]-[i]}(i<k<j)

其中a[j]-a[i]表示从i到j的长度,即要切这块木条所需的花费。求大区间得时候小区间已经算出来了,所以符合动态规划的自底向上,而且是最优子结构,这道题我把0和木条长度加到了a数组里面,就是说一共有n+2个点,每两个相邻的点不用切割,初始化为1。

代码如下:

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=400010;
const int mo=1e9+7;
int dp[60][60];
int a[60];
int cnt,tmp,ans;
int k,l;
int main()
{
    int n,m,T,cas;
    while(scanf("%d",&l)!=EOF&&l)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
        }
        a[0]=0;
        a[n+1]=l;
        m=n+1;
        for(int i=0;i<m;i++)
        dp[i][i+1]=0;
        memset(dp,0,sizeof(dp));
        for(int p=2;p<=m;p++)//length
        {
            for(int i=0;i<=m+1-p;i++)//start
            {
                int j=i+p;
                int mi=mo;
                for(int k=i+1;k<j;k++)
                {
                    tmp=dp[i][k]+dp[k][j]+a[j]-a[i];
                    if(tmp<mi) mi=tmp;
                }
                if(mi!=mo) dp[i][j]=mi;
            }
        }
        printf("The minimum cutting is %d.\n",dp[0][m]);
    }
    return 0;
}

附:

1 区间DP
2   区间动态规划问题一般都是考虑,对于每段区间,他们的最优值都是由几段更小区间的最优值得到。将一个区间问题不断划分为更小的区间直至一个元素组成的区间,枚举他们的组合,求合并后的最优值。
3 设F[i,j](1<=i<=j<=n)表示区间[i,j]内的数字相加的最小代价 , 最小区间F[i,i]=0(一个数字无法合并,∴代价为0)每次用变量k(i<=k<=j-1)将区间分为[i,k]和[k+1,j]两段
4《区间DP模板,代码》
                     for(intp = 1 ; p <= n ; p++){//p是区间的长度,作为阶段
                         for(int i = 1 ; i <= n ; i++)
{//i是穷举区间的起点
                              int j = i+p-1;//j为区间的终点
                             for(int k = i ; k < j ; k++)//状态转移
                                 dp[i][j] = min{dp[i][k]+dp[k+1][j]+w[i][j]};
//这个是看题目意思,有的是要从k开始不是k+1
                               dp[i][j]= max{dp[i][k]+dp[k+1][j]+w[i][j]};
                        }
                       }

猜你喜欢

转载自blog.csdn.net/LSD20164388/article/details/80372082