石子合并 nyoj737 区间dp
2017-07-18 19:09
281 查看
题意:
有N堆石子排成一排,每堆石子有一定的数量。现要将N堆石子并成为一堆。合并的过程只能每次将相邻的两堆石子堆成一堆,并将新的一堆石子数记为该次合并的代价。求最小代价。思路
我们假设dp[i][j]是从i到j区间的最优解。我们想知道,能否像建塔一样,知道了底层的就可以建立高层的。
这里我们以 j-i 的值为dp分层,也就是分为区间长度为1的,2的,3的…n的。
一个问题摆在面前,能否用低层次的砌高层次的。显然是可以的,这也是比较重要的地方。
很显然一个大的区间,必然是由构成他的,两个小的区间构成,比如区间[2 5],必然是有下列三对 区间 之一组合构成:[2 2][3 5] ; [2 3][4 5] ; [2 4][5 5];
总结一下,求区间dp[i][j]=min{dp[i][j+k]+dp[k+1][j]+代价函数} 其中(k=0,1,2…j-i )。
以下是参考代码:
#include<cstdio> #include<algorithm> #include<cstring> #include<iostream> #include<cmath> int dp[205][205]; int an[205]; int cn[205]; int sum(int a,int b){ return cn[b]-cn[a-1]; } int minn(int a,int b){ return a<b? a:b; } int main(){ int n; while(~scanf("%d",&n)){ for(int i=1;i<=n;i++) scanf("%d",&an[i]); memset(cn,0,sizeof(cn)); for(int i=1;i<=n;i++) cn[i]=cn[i-1]+an[i]; memset(dp,0,sizeof(dp)); for(int i=1;i<n;i++){ //枚举区间长度 i+1 for(int j=1;j+i<=n;j++){//枚举区间左端点 for(int k=1;k<=i;k++){//枚举分割点,前k个为一组 if(dp[j][j+i]==0) dp[j][j+i]=dp[j][j+k-1]+dp[j+k][j+i]+sum(j,j+i); dp[j][j+i]=minn(dp[j][j+i],dp[j][j+k-1]+dp[j+k][j+i]+sum(j,j+i)); //状态转移方程 } } } printf("%d\n",dp[1] ); } }
相关文章推荐
- nyoj737 区间dp(合并石子)
- nyoj737 石子合并(一)(区间dp)
- NYOJ737 石子合并(区间DP)
- nyoj737 石子合并 区间dp
- nyoj737 石子合并(一) 区间DP
- Hrbust 1819 石子合并问题--圆形版【环形区间Dp】
- lanqiao 小白算法练习 合并石子 区间dp
- 石子合并问题--圆形版(区间DP)
- 区间dp 石子合并
- (区间dp)南阳理工 acm 737 石子合并(一)
- tyvj 1055 沙子合并 区间dp经典模型,石子合并
- nyoj 737 石子合并(一)(区间DP)
- 洛谷OJ - P1880 - 石子合并(区间DP)
- 记忆化搜索或区间DP——石子合并
- NYOJ 737 石子合并(一) (区间DP+平行四边形优化)
- 石子合并(区间dp)
- nyoj 737 石子合并(一) 【区间dp】
- nyoj 737 石子合并(一)(区间DP)
- nyistOJ-石子合并(一)(区间DP)
- HDU 3506 (环形石子合并)区间dp+四边形优化