区间DP-石子合并(线性)
来源:互联网 发布:淘宝诈骗卖家如何应对 编辑:程序博客网 时间:2024/05/22 15:04
石子合并(一)
时间限制:1000 ms | 内存限制:65535 KB
难度:3
- 描述
- 有N堆石子排成一排,每堆石子有一定的数量。现要将N堆石子并成为一堆。合并的过程只能每次将相邻的两堆石子堆成一堆,每次合并花费的代价为这两堆石子的和,经过N-1次合并后成为一堆。求出总的代价最小值。
- 输入
- 有多组测试数据,输入到文件结束。
每组测试数据第一行有一个整数n,表示有n堆石子。
接下来的一行有n(0< n <200)个数,分别表示这n堆石子的数目,用空格隔开 - 输出
- 输出总代价的最小值,占单独的一行
- 样例输入
31 2 3713 7 8 16 21 4 18
- 样例输出
9239
- 来源
题目在:
Here
这是一道经典的区间DP,做出来也花了不少时间,具体注释见代码。这里要注意的是sum数组是一个前缀和数组,需要注意的一点就是sum[i]=a[0]+a[1]+...+a[i];
sum[j]=a[0]+a[1]+a[2]+...+a[j],那么显然sum[i~j]=sum[j]-sum[i]+a[i],即sum[i~j]=sum[j]-sum[i-1].不然会减去a[i]。。
还有就是记忆化搜索这块儿,题目说最终合并为一堆,那么当本来只有一堆的时候合并代价是0,我写成了num[i]。注意这几点便可以把这道问题解决了。
/***************************************************** author:crazy_石头* Pro:石子合并问题* algorithm:区间DP* Time:420ms* Judge Status:Accepted*******************************************************/#pragma comment(linker, "/STACK:102400000,102400000")#include <iostream>#include <cstring>#include <cstdlib>#include <cstdio>#include <queue>#include <vector>#include <algorithm>using namespace std;#define rep(i,h,n) for(int i=(h);i<=(n);i++)#define ms(a,b) memset((a),(b),sizeof(a))#define eps 1e-6#define INF 1<<29#define LL __int64const int maxn=200+5;const int maxm=1000000+10;int dp[maxn][maxn];int sum[maxn],num[maxn];inline int dfs(int i,int j){ if(dp[i][j]!=INF)return dp[i][j]; if(i==j)return dp[i][j]=0;//题目要合并为一堆,如果本身是一堆,那么不用合并,即代价为0; if(i+1==j)return dp[i][j]=num[i]+num[j];//两堆的话,合并代价等于这两堆的数量相加; if(i>j)return dp[i][j]=0; //其余情况,将大范围划小,则i~j间花费的费用等于i~k的代价加上k+1到j的代价并加上i~j间石子数目; for(int k=i;k<j;k++) dp[i][j]=min(dp[i][j],dfs(i,k)+dfs(k+1,j)+sum[j]-sum[i-1]); return dp[i][j];}int main(){ int test,n; while(cin>>n) { int m; ms(sum,0); cin>>num[0]; sum[0]=num[0]; for(int i=1;i<n;i++) { cin>>num[i]; sum[i]=sum[i-1]+num[i]; } for(int i=0;i<n;i++) { for(int j=0;j<n;j++) { dp[i][j]=INF; } } int res=dfs(0,n-1); printf("%d\n",res); } return 0;}
- 区间DP-石子合并(线性)
- 石子合并 (区间DP)
- 石子合并 (区间dp)
- 石子合并(区间dp)
- <区间DP> 石子合并
- [区间DP]石子合并
- 合并石子,区间DP
- 石子合并【区间dp】
- 区间dp 石子合并
- 石子合并~区间dp基础
- 石子合并与区间dp
- 石子合并(区间dp)
- 石子合并 (区间DP)
- nyoj+区间dp石子合并
- nyoj737石子合并【区间dp】
- nyoj737 石子合并 区间dp
- 区间DP-NYOJ737石子合并
- 【tyvj】【区间dp】石子合并
- 游戏盒子接球
- php学习之字符串转换
- hdu-1071 The area
- 啊各位
- 合并不同目录下,相同文件的内容(java实现)
- 区间DP-石子合并(线性)
- 使用命名空间、头文件和实现文件
- 奋斗的小蜗牛
- Good Substrings
- exp逻辑全备份脚本for AIX
- nyoj11——奇偶数分离
- 文件输入输出的例子
- nyoj13——Fibonacci数
- 内存地址