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