题目描述
在一个圆形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分。
试设计出1个算法,计算出将N堆石子合并成1堆的最小得分和最大得分.
输入输出格式
输入格式:
数据的第1行试正整数N,1≤N≤100,表示有N堆石子.第2行有N个数,分别表示每堆石子的个数.
输出格式:
输出共2行,第1行为最小得分,第2行为最大得分.
输入输出样例
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int MAXN=310; 4 const int INF=0x3f3f3f3f; 5 int dp[MAXN][MAXN],sum[MAXN],ans[MAXN],DP[MAXN][MAXN]; 6 int jian(int i,int j){ return sum[j]-sum[i-1]; }//i-1是因为前缀和要减去前一个而不是当前的那个。 7 int main() 8 { 9 int n; 10 scanf("%d",&n); 11 for (int i = 1; i <=n ; ++i) { 12 scanf("%d",&ans[i]); 13 } 14 for (int i = 1; i <=n+n ; ++i) {//拆开环,双向 15 ans[i+n]=ans[i]; 16 sum[i]=ans[i]+sum[i-1];//前缀和 17 } 18 memset(dp,0, sizeof(dp)); 19 for (int l = 1; l <n ; ++l) {// 步长 ,l==1时,步长为二 20 for (int i = 1,j=i+l; (j<n+n)&&(i<n+n) ; ++i,j=i+l) { 21 DP[i][j]=INF; 22 for (int k = i; k <j ; ++k) {//每一步当中的分割点 23 dp[i][j]=max(dp[i][j],dp[i][k]+dp[k+1][j]+jian(i,j));//l-r的最大值 24 DP[i][j]=min(DP[i][j],DP[i][k]+DP[k+1][j]+jian(i,j)); 25 } 26 } 27 } 28 int MAX=0,MIN=INF; 29 for(int i=1;i<=n;i++) 30 { 31 MAX=max(MAX,dp[i][i+n-1]); 32 MIN=min(MIN,DP[i][i+n-1]); 33 } 34 printf("%d %d ",MIN,MAX); 35 return 0; 36 }