P1880 石子合并
2017-07-17 21:06
267 查看
P1880 石子合并
题目描述
在一个园形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分。
试设计出1个算法,计算出将N堆石子合并成1堆的最小得分和最大得分.
输入输出格式
输入格式:
数据的第1行试正整数N,1≤N≤100,表示有N堆石子.第2行有N个数,分别表示每堆石子的个数.
输出格式:
输出共2行,第1行为最小得分,第2行为最大得分.
输入输出样例
输入样例#1:4 4 5 9 4输出样例#1:
43 54
分析
区间dp,不过是圆形的,把他们分成一个n*2的区间就好,然后进行区间dp ,对dp1不能全设成最大值,不然没法取min。
最后要在所有区间长度为n的区间中取出最大值与最小值。
code
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int MAXN = 210; int dp1[MAXN][MAXN],dp2[MAXN][MAXN],a[MAXN],sum[MAXN]; int n,ans1 = 2147483647,ans2 = 0; int main() { scanf("%d",&n); for (int i=1; i<=n*2; ++i) for (int j=i+1; j<=n*2; ++j) dp1[i][j] = 1e8; //最小值 memset(dp2,0,sizeof(dp2)); //最大值 for (int i=1; i<=n; ++i) { scanf("%d",&a[i]); a[i+n] = a[i]; } for (int i=1; i<=n*2; ++i) sum[i] = sum[i-1]+a[i]; for (int i=2*n-1; i>=1; --i)//从倒数第二个开始枚举左端点 for (int j=i+1; j<=2*n; ++j)//枚举右端点 for (int k=i; k<=j-1; ++k)//枚举中间点 dp1[i][j] = min(dp1[i][j],dp1[i][k]+dp1[k+1][j]+sum[j]-sum[i-1]), dp2[i][j] = max(dp2[i][j],dp2[i][k]+dp2[k+1][j]+sum[j]-sum[i-1]); for (int i=1; i<=n; ++i) { ans1 = min(ans1,dp1[i][i+n-1]); ans2 = max(ans2,dp2[i][i+n-1]); } printf("%d\n%d",ans1,ans2); return 0; }
相关文章推荐
- P1880 [NOI1995]石子合并
- 【洛谷P1880】合并石子
- 【P1880】石子合并(环形)
- p1880石子合并 题解
- P1880 [NOI1995]石子合并(区间dp)
- 【洛谷】P1880 石子合并
- [LUOGU] P1880 [NOI1995]石子合并
- 【洛谷】P1880 石子合并
- DP 洛谷 P1880 [NOI1995]石子合并
- (ssl1597)P1880 石子合并问题
- 洛谷P1880 石子合并
- 洛谷P1880 石子合并
- 洛谷 P1880 石子合并
- P1880 石子合并
- 洛谷 P1880 石子合并
- 洛谷 p1880 石子合并 区间dp
- P1880 石子合并
- 洛谷 P1880 [NOI1995]石子合并
- P1880 [NOI1995]石子合并
- 【p1880】石子合并