描述
在一个圆形操场的四周摆放着n 堆石子。现要将石子有次序地合并成一堆。规定每次只能选相邻的2 堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的得分。试设计一个算法,计算出将n堆石子合并成一堆的最小得分和最大得分。
输入
在每组测试数据中。第1行是正整数n,表示有n堆石子。第2 行有n个数,分别表示每堆石子的个数。
输出
程序运行结束时,将计算结果输出。第1 行中的数是最小得分;第2 行中的数是最大得分。
样例输入
4
4 4 5 9
4 4 5 9
样例输出
43
54
54
#include <iostream> #include <stdio.h> #include <string.h> #include <string> #include <limits.h> using namespace std; int dpx[1100][110],p[1100][1100],s[1100],dp[1100][1100]; int anx,any; int main() { int n; while(cin>>n) { memset(p,0,sizeof(p)); for(int i=1;i<=n;i++) { cin>>s[i]; s[n+i]=s[i]; } for(int i=1;i<=2*n;i++) { p[i][i]=s[i]; for(int j=i+1;j<=2*n;j++) p[i][j]=p[i][j-1]+s[j]; } memset(dp,0,sizeof(dp)); for(int r=1;r<n;r++) { for(int i=1;i<=2*n-r;i++) { int j=r+i; dpx[i][j]=INT_MAX; for(int k=i;k<j;k++) { dp[i][j]=max(dp[i][j],dp[i][k]+dp[k+1][j]+p[i][j]); dpx[i][j]=min(dpx[i][j],dpx[i][k]+dpx[k+1][j]+p[i][j]); } } } anx=0; any=INT_MAX; for(int i=1;i<=n;i++) { anx=max(anx,dp[i][n+i-1]); any=min(any,dpx[i][n+i-1]); } printf("%d\n",any); printf("%d\n",anx); } return 0; }