[ifrog 1066 - Buy Candy] 四边形优化的石子合并
1. 题目链接
2. 题意描述
给定
N
组人,现在需要将这
f(x)=∑i=0m(ai∗xi);【ai是系数】
求合并的最小代价。 (1≤n≤1000,1≤m≤4) 。
3. 解题思路
首先,如果不知道“石子合并”或者“四边形优化”的可以点击下面的链接进行学习。
然后,我们可以很容易写出DP方程,如下:
dp[i][j]=min{dp[i][k]+dp[k+1][j]+sum[i,j]};
【sum[i,j]表示】区间[i,j]元素之和。可以用一个前缀和来处理。
最后,用四边形不等式优化一下。
4. 实现代码
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
const int MAXN = 1000 + 5;
const int INF = 0x3f3f3f3f;
int n, m, s[MAXN], a[MAXN];
int p[MAXN][MAXN], sum[MAXN];
LL dp[MAXN][MAXN];
LL calc(int x) {
LL ret = 0, z = 1;
for(int i = 0; i <= m; i++) {
ret += a[i] * z;
z *= x;
}
return ret;
}
int main() {
#ifndef ONLINE_JUDGE
// freopen("input.txt", "r", stdin);
#endif // ONLINE_JUDGE
int _;
scanf("%d", &_);
while(_ --) {
scanf("%d", &n);
for(int i = 1; i <= n; i++) scanf("%d", &s[i]);
scanf("%d", &m);
for(int i = 0; i <= m; i++) scanf("%d", &a[i]);
memset(dp, 0x3f, sizeof(dp));
sum[0] = 0;
for(int i = 1; i <= n; i++) {
dp[i][i] = 0;
p[i][i] = i;
sum[i] = sum[i - 1] + s[i];
}
for(int len = 2; len <= n; len++) {
for(int i = 1; i + len - 1 <= n; i++) {
int j = i + len - 1;
for(int k = p[i][j - 1]; k <= p[i + 1][j]; k++) {
LL val = dp[i][k] + dp[k + 1][j] + calc(sum[j] - sum[i - 1]);
if(val < dp[i][j]) {
dp[i][j]= val;
p[i][j] = k;
}
}
}
}
printf("%lld\n", dp[1][n]);
}
return 0;
}