石子合并[DP-N3]
2016-08-31 15:18
225 查看
题目描述
在一个园形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分。试设计出1个算法,计算出将N堆石子合并成1堆的最小得分和最大得分.
输入输出格式
输入格式:数据的第1行试正整数N,1≤N≤100,表示有N堆石子.第2行有N个数,分别表示每堆石子的个数.
输出格式:
输出共2行,第1行为最小得分,第2行为最大得分.
--------------------------------------------------------
环形DP,前缀和,O(n3)即可
可以i降序j升序,也可以枚举长度
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> using namespace std; const int N=105<<2,INF=1e9; int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int n,a ,mx=0,mn=INF; int f ,s ,d ; void dp(){ for(int i=1;i<=2*n;i++)for(int j=1;j<=2*n;j++) d[i][j]=INF,d[i][i]=0; for(int i=1;i<=2*n;i++) s[i]=s[i-1]+a[i]; // for(int i=2*n-1;i>=1;i--) // for(int j=i+1;j<=2*n&&j-i<n;j++) // for(int k=i;k<j;k++){ // f[i][j]=max(f[i][j],f[i][k]+f[k+1][j]+s[j]-s[i-1]); // d[i][j]=min(d[i][j],d[i][k]+d[k+1][j]+s[j]-s[i-1]); // } for(int l=1;l<n;l++) for(int i=1;i<=2*n;i++){ int j=min(2*n,i+l); for(int k=i;k<j;k++){ f[i][j]=max(f[i][j],f[i][k]+f[k+1][j]+s[j]-s[i-1]); d[i][j]=min(d[i][j],d[i][k]+d[k+1][j]+s[j]-s[i-1]); } } } int main(int argc, const char * argv[]) { n=read(); for(int i=1;i<=n;i++) a[i]=read(),a[i+n]=a[i]; dp(); for(int i=1;i<=n;i++) mx=max(f[i][i+n-1],mx),mn=min(mn,d[i][i+n-1]); printf("%d\n%d",mn,mx); return 0; }
相关文章推荐
- 蓝桥杯 —— 石子合并问题 —— Dp
- 石子(环形)合并问题_dp
- 区间dp讲解之石子合并问题 区间dp的分析方法
- 区间DP-合并石子(求最小/最代价 )
- nyoj737石子合并【区间dp】
- nyoj 737 石子合并(一)。区间dp
- bzoj3229 [Sdoi2008]石子合并(非dp的GarsiaWachs算法)
- nyoj 737 石子合并(一)(区间DP)
- lanqiao 小白算法练习 合并石子 区间dp
- DP石子合并问题
- NYOJ- 737 石子合并(一)(dp+多种方法实现)
- 记忆化搜索或区间DP——石子合并
- 石子合并 (区间DP)
- 石子合并 区间dp 2018-3-6
- nyoj737 区间dp(合并石子)
- 合并石子(区间dp)
- 经典:区间dp-合并石子
- 石子合并 nyoj737 区间dp
- NYOJ_737_石子合并(一)【区间DP】
- nyoj 737 石子合并(一)(区间DP)