题目描述
在一个圆形操场的四周摆放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
*****石子合并分为两个梯度的形式
第一种就是一条线那样的石子合并
1 #include<cstdio> 2 #include<cstring> 3 #include<cmath> 4 #include<algorithm> 5 using namespace std; 6 int i,j,l,k,n,a[105],f[105][105],s[105]; 7 int main() 8 { 9 scanf("%d",&n); 10 s[0] = 0; 11 for(i = 1;i <= n;i++) 12 { 13 scanf("%d",&a[i]); 14 s[i] = s[i - 1] + a[i]; 15 } 16 for(l = 2;l <= n;l++) 17 { 18 for(i = 1;i <= n + l - 1;i++) 19 { 20 j = i + l - 1; 21 for(k = i;k <= j - 1;k++) 22 { 23 if(f[i][j] != 0) 24 f[i][j] = min(f[i][j],f[i][k] + f[k + 1][j] + s[j] - s[i - 1]); 25 else 26 f[i][j] = f[i][k] + f[k + 1][j] + s[j] - s[i - 1]; 27 } 28 } 29 } 30 printf("%d",f[1][n]); 31 return 0; 32 }
第二种是围成一个圈那样,和这道题就是这个类型
O(N^3)有两种算法
第一种就是
这种啊博主也没怎么看懂,等着2020年6月9号看吧吼吼
下面这种博主还是会滴
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cmath> 5 using namespace std; 6 int i,j,m,n,l,k,da = 0,an = 0,a[205],f[205][205],s[205],p[205][205]; 7 int main() 8 { 9 scanf("%d",&n); 10 s[0] = 0; 11 for(i = 1;i <= n;i++) 12 { 13 scanf("%d",&a[i]); 14 a[i + n] = a[i]; 15 } 16 for(i = 1;i <= 2 * n;i++) 17 { 18 s[i] = s[i - 1] + a[i]; 19 } 20 for(l = 2;l <= n;l++) 21 { 22 for(i = 1;i <= n * 2 - l;i++) 23 { 24 j = i + l - 1; 25 for(k = i;k <= j - 1;k++) 26 { 27 if(f[i][j] != 0) 28 f[i][j] = min(f[i][j],f[i][k] + f[k + 1][j] + s[j] - s[i - 1]); 29 else 30 f[i][j] = f[i][k] + f[k + 1][j] + s[j] - s[i - 1]; 31 p[i][j] = max(p[i][j],p[i][k] + p[k + 1][j] + s[j] - s[i - 1]); 32 } 33 } 34 } 35 for(i = 1;i <= n;i++) 36 { 37 if(da != 0) 38 da = min(da,f[i][i + n - 1]); 39 else 40 da = f[i][i + n - 1]; 41 an = max(an,p[i][i + n - 1]); 42 } 43 printf("%d %d",da,an); 44 return 0; 45 }