石子合并
2018-01-20 16:11
465 查看
P1880 [NOI1995]石子合并
题目描述
在一个圆形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分。
试设计出1个算法,计算出将N堆石子合并成1堆的最小得分和最大得分.
状态转移方程的定义: dp( l , r ) 的含义是合并l - r这段区间的石子所能获得的最大值,那么,合并第i颗石子的最大值就是左边的加右边的
环形的……
题目描述
在一个圆形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分。
试设计出1个算法,计算出将N堆石子合并成1堆的最小得分和最大得分.
状态转移方程的定义: dp( l , r ) 的含义是合并l - r这段区间的石子所能获得的最大值,那么,合并第i颗石子的最大值就是左边的加右边的
环形的……
#include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<cmath> #include<algorithm> using namespace std; const int MAXN = 205; int Max[MAXN][MAXN],Min[MAXN][MAXN]; int sum[205]; int dp(int l,int r) { if(Max[l][r]) { return Max[l][r]; } if(l == r) { return 0; } int t1 = 0; for(int i = l; i < r; i++) { t1 = max(dp(l, i) + dp(i + 1, r) + sum[r] - sum[l - 1],t1); //为什么要加上 sum[r] - sum[l - 1] //因为合并一次,要消耗的值就是l - r的石子中数之和 } return Max[l][r] = t1; } int dp2(int l ,int r) { if(Min[l][r]) { return Min[l][r]; } if(l == r) { return Min[l][r] = 0; } int t1 = 999999; for(int i = l; i < r; i++) { t1 = min(dp2(l, i) + dp2(i + 1, r) + sum[r] - sum[l - 1],t1); } return Min[l][r] = t1; } int main() { int n; cin>>n; for(int i = 1; i<=n; i++) { cin>>sum[i]; sum[i+n] = sum[i]; } for(int i = 1; i <= 2*n; i++) sum[i] += sum[i - 1]; dp2(1,2*n); dp(1,2*n); int minn = 999999,maxn = 0; for(int i = 1; i<=n; i++) { minn = min(Min[i][n+i-1],minn); } cout<<minn<<endl; for(int i = 1; i<=n; i++) { maxn = max(Max[i][n+i-1],maxn); } cout<<maxn; return 0; }
相关文章推荐