环形石子合并
题目描述
在一个圆形操场的四周摆放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
算法:动态规划
#include<iostream> #include<cstdio> #include<limits.h> #include<cstring> #include<algorithm> using namespace std; const int N=310; int n,mil,mxl,f1[N][N],f2[N][N],a[N]; int s[N]; int main() { cin>>n; memset(f1,0x3f,sizeof(f1)); for(int i=1;i<=n+n;i++) { cin>>a[i]; a[i+n]=a[i]; s[i]=s[i-1]+a[i]; f1[i][i]=0; } for(int i=2;i<=n;i++) { for(int j=1;j<=2*n-i+1;j++){ int l=j,r=j+i-1; for(int k=l;k<r;k++){ f1[l][r]=min(f1[l][r],f1[l][k]+f1[k+1][r]+s[r]-s[l-1]); f2[l][r]=max(f2[l][r],f2[l][k]+f2[k+1][r]+s[r]-s[l-1]); } } } mil=INT_MAX; for(int i=1;i<=n;i++) { mxl=max(mxl,f2[i][i+n-1]); mil=min(mil,f1[i][i+n-1]); } cout<<mil<<endl; cout<<mxl; return 0; }