Pangu and Stones 北京2017ICPC(三维区间DP)

Posted gzr2018

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Pangu and Stones 北京2017ICPC(三维区间DP)相关的知识,希望对你有一定的参考价值。

题意:

合并石子的升级版。一堆石子,编号为1到n,每堆石子有其权值,一次只能合并连续的石子L到R堆,每次合并的代价为各堆石子的权值,求最后一堆的最小代价,不能完成输出0。

思路:

考虑区间dp做法,因为这个题与堆数有关,dp中加入一维堆数。

dp[i[[j][p]表示石子从i到j合并成p堆的最小花费,状态很重要。

状态转移:

当p>1&&i<=k<j(不表示合并,只表示合并的方案)

dp[i][j][p]=dp[i][k][1]+dp[k+1][j][p-1](表示区间i到j分成p堆的方案枚举,因为p堆总数1堆+p-1堆)

当p==1&&L<=p<=R(表示真正的合并)

dp[i][j][1]=dp[i][j][p]+pre[j]-pre[i-1]。

初始化:

求最小,首先f把需要用的的数组范围内的初始化INF

dp[i][i][1]=0,表示没有合并的自己不需要代价

也存在一些边界条件处理,自己注意一下即可。

代码:

 

#include <iostream>
#include<bits/stdc++.h>
using namespace std;
const int N=105;
int dp[N][N][N];//区间i到j分成k堆的最小代价
const int INF=0x3f3f3f3f;
int a[N];
int pre[N];
void init(int n)
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    
    for(int i=1;i<=n;i++)
        pre[i]=pre[i-1]+a[i];
    
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            for(int k=1;k<=n;k++)
                dp[i][j][k]=INF;
    for(int i=0;i<N;i++)
        dp[i][i][1]=0;

int main()

    int n,l,r;
    while(~scanf("%d%d%d",&n,&l,&r))
        init(n);
    for(int len=1;len<=n;len++)
        for(int i=1;i+len-1<=n;i++)
            int j=i+len-1;
            for(int p=2;p<=len;p++)
            
                for(int k=i;k<j&&j-k>=p-1;k++)
                
                    dp[i][j][p]=min(dp[i][j][p],dp[i][k][1]+dp[k+1][j][p-1]);
                    if(p>=l&&p<=r)dp[i][j][1]=min(dp[i][j][1],dp[i][j][p]+pre[j]-pre[i-1]);
                
            
    
    if(dp[1][n][1]==INF)
        printf("0\n");
    
    else
        printf("%d\n",dp[1][n][1]);
    
    
    return 0;

 

以上是关于Pangu and Stones 北京2017ICPC(三维区间DP)的主要内容,如果未能解决你的问题,请参考以下文章

2017北京ICPC Pangu and Stones(区间DP)

Pangu and Stones 北京2017ICPC(三维区间DP)

Pangu and Stones(HihoCoder-1636)(17北京OL)区间DP

hihocoder1636 Pangu and Stones

hihoCoder 1636 Pangu and Stones

Pangu and Stones HihoCoder - 1636 区间DP