标签:memset 转移 cst ems else min space img string
题意:有n堆石头,盘古每次可以选择连续的x堆合并,所需时间为x堆石头的数量之和,x∈[l,r],现在要求,能否将石头合并成一堆,如果能,最短时间是多少。
思路:(参考了ACM算法日常)DP[i][j][k],表示当前状态下[i,j]这个区间分成了k堆。
状态转移:1.k=1时,dp[i][j][k]=min(dp[i][j][D]+num[j]-num[i-1]),其中D∈[l,r],
2.k!=1时,dp[i][j][k]=min(dp[i][z][1]+dp[z+1][j][k-1]),(合并成k堆时,可以转化为k-1堆与1堆合并,此时就是区间DP的思路了)
代码如下:
#include<cstdio> #include<cstring> #include<iostream> using namespace std; int n,l,r,a[110]; int dp[110][110][110],num[110]; int main(){ while(~scanf("%d%d%d",&n,&l,&r)){ num[0]=0; memset(dp,0x3f,sizeof(dp)); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); num[i]=num[i-1]+a[i]; } for(int i=1;i<=n;i++) dp[i][i][1]=0; for(int i=2;i<=n;i++){ for(int j=1;j+i-1<=n;j++){ for(int k=i;k>=1;k--){ if(k==1){ for(int z=l;z<=r;z++) dp[j][j+i-1][k]=min(dp[j][j+i-1][k],dp[j][j+i-1][z]+num[j+i-1]-num[j-1]); } else { for(int z=j;z<j+i-1;z++) dp[j][j+i-1][k]=min(dp[j][j+i-1][k],dp[j][z][1]+dp[z+1][j+i-1][k-1]); } } } } if(dp[1][n][1]==0x3f3f3f3f) printf("0\n"); else printf("%d\n",dp[1][n][1]); } return 0; }
Pangu and Stones(HihoCoder-1636)(17北京OL)【区间DP】
标签:memset 转移 cst ems else min space img string
原文地址:https://www.cnblogs.com/xxmlala-fff/p/11621978.html