这是一道经典的动态规划问题。设f[i][j]表示合并第i个到第j个石子所得的最小得分,f[i][j] = min{f[i][j], f[i][k - 1] + f[k][j] + sum[j] - sum[i - 1]} (i < k <= j),时间复杂度是O(n3).
这道题可用平行四边形优化到O(n2),不过这个优化虽然会照着写,但还不太明白……
http://acm.nankai.edu.cn/p1137.html
这道题注意是圆形,否则会WA的,数据范围小,不需要优化
///http://acm.nankai.edu.cn/p1137.html
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define LL long long
const LL INF = (LL)1<<60;
LL sum[210], f[210][210], d[210][210], num[210];
int main()
{
//freopen("input.txt", "r", stdin);
int n;
LL ans1, ans2;
while(cin >> n){
sum[0] = 0;
for(int i = 1; i <= n; i++){
cin>>num[i];
sum[i] = sum[i - 1] + num[i];
}
for(int i = 1; i < n; i++){
num[i + n] = num[i];
sum[i + n] = sum[i + n - 1] + num[i + n];
}
memset(f, 0, sizeof(f));
memset(d, 0, sizeof(d));
for(int l = 2; l <= n; l++){
for(int i = 1, j; i + l - 1 < 2 * n; i++){
j = i + l - 1;
f[i][j] = INF;
for(int k = i; k < j; k++){
f[i][j] = min(f[i][j], f[i][k] + f[k + 1][j] + sum[j] - sum[i - 1]);
d[i][j] = max(d[i][j], d[i][k] + d[k + 1][j] + sum[j] - sum[i - 1]);
}
}
}
ans1 = INF;
ans2 = 0;
for(int i = 1; i <= n; i++){
ans1 = min(ans1, f[i][i + n - 1]);
ans2 = max(ans2, d[i][i + n - 1]);
}
cout<<ans1<<endl<<ans2<<endl;
}
return 0;
}
http://coder.buct.edu.cn/oj/Problem.aspx?pid=1725
用到了平行四边形优化
//四边形优化 http://coder.buct.edu.cn/oj/Problem.aspx?pid=1725
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define LL long long
const LL INF = (LL)1<<60;
const int MAXN = 1010;
LL sum[MAXN], f[MAXN][MAXN], prt[MAXN][MAXN], num[MAXN];
int main()
{
//freopen("input.txt", "r", stdin);
int n;
while(cin >> n){
sum[0] = 0;
for(int i = 1; i <= n; i++){
cin>>num[i];
sum[i] = sum[i - 1] + num[i];
}
memset(f, 0, sizeof(f));
memset(prt, 0, sizeof(prt));
for(int i = 1; i <= n; i++) prt[i][i] = i;
for(int l = 2; l <= n; l++){
for(int i = 1, j; i <= n - l + 1; i++){
j = i + l - 1;
f[i][j] = INF;
for(int k = prt[i][j - 1]; k <= prt[i + 1][j]; k++){
if(f[i][j] > f[i][k - 1] + f[k][j]){
f[i][j] = f[i][k - 1] + f[k][j];
prt[i][j] = k;
}
}
f[i][j] += sum[j] - sum[i - 1];
}
}
cout<<f[1][n]<<endl;
}
return 0;
}