在一个圆形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分。
试设计出1个算法,计算出将N堆石子合并成1堆的最小得分和最大得分.
数据的第1行试正整数N,1≤N≤100,表示有N堆石子.第2行有N个数,分别表示每堆石子的个数.
输出共2行,第1行为最小得分,第2行为最大得分.
4
4 5 9 4
43
54
none
#include<bits/stdc++.h>
#define LL long long
LL in() {
char ch; LL x = 0, f = 1;
while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
return x * f;
}
const int maxn = 350;
const int inf = 0x3f3f3f3f;
int n;
int f[maxn][maxn], g[maxn][maxn], s[maxn], a[maxn], min = inf, max, pos[maxn][maxn];
int main() {
n = in();
for(int i = 1; i <= n; i++) a[i + n] = a[i] = in();
for(int i = 1; i <= (n << 1); i++) s[i] = s[i - 1] + a[i], pos[i][i] = i;
for(int L = 2; L <= n; L++) {
for(int l = 1, r = l + L - 1; r <= (n << 1); l++, r++) {
g[l][r] = inf;
for(int k = pos[l][r - 1]; k <= pos[l + 1][r]; k++) {
int now = g[l][k] + g[k + 1][r] + s[r] - s[l - 1];
if(g[l][r] > now) g[l][r] = now, pos[l][r] = k;
}
f[l][r] = std::max(f[l][r], std::max(f[l][l] + f[l + 1][r], f[l][r - 1] + f[r][r]) + s[r] - s[l - 1]);
if(L == n) max = std::max(max, f[l][r]), min = std::min(min, g[l][r]);
}
}
printf("%d\n%d", min, max);
return 0;
}
原文:https://www.cnblogs.com/olinr/p/10420194.html