Monkey Party(动态规划-区间dp-四边形不等式优化)
judge:HDUOJ 3506
Time Limit: 4000/2000 MS (Java/Others)
Memory Limit: 131072/65536 K (Java/Others)
source:2010 ACM-ICPC Multi-University Training Contest(7)——Host by HIT
Problem Description
Far away from our world, there is a banana forest. And many lovely monkeys live there. One day, SDH(Song Da Hou), who is the king of banana forest, decides to hold a big party to
HDUOJ 3506
Input
Output
Sample Input
8
5 2 4 7 6 1 3 9
Sample Output
105
题意
n个猴子围成一个圈,每个猴子都需要交朋友。当一个猴子和别的猴子交朋友时这个猴子认识的猴子也会认识了这个新猴子,不过消耗的时间则是这些猴子所有的自我介绍的时间的总和。而我们要做的就是把那些自我介绍时间长的猴子尽可能少介绍,以达到总时间最少的目的
还有一个要注意的点是猴子是围成一个圈的,所以把数组往后复制一份来模拟一个圈。
四边形不等式优化具体怎么证明我也不太会,先贴在这,以后有机会再研究。
代码
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#define _for(i, a) for(int i = 0; i < (a); i++)
#define _rep(i, a, b) for(int i = (a); i <= (b); i++)
typedef long long ll;
const int maxn = 2005;
const int inf = 0x3f3f3f3f;
using namespace std;
int dp[maxn][maxn];
int a[maxn];
int s[maxn][maxn];
int n;
int main() {
//freopen("in.txt", "r", stdin);
while (cin >> n) {
memset(dp, 0x3f, sizeof(dp));
memset(a, 0, sizeof(a));
_rep(i, 1, n) {
cin >> a[i];
a[i + n] = a[i];
}
n *= 2;
_rep(i, 1, n) a[i] += a[i - 1], dp[i][i] = 0, s[i][i] = i;
_rep(d, 2, n / 2) {
for (int i = 1, j = i + d - 1; j <= n; i++, j++) {
_rep(k, s[i][j - 1], s[i + 1][j]) {
if (dp[i][j] > dp[i][k] + dp[k + 1][j] + a[j] - a[i - 1]) {
dp[i][j] = dp[i][k] + dp[k + 1][j] + a[j] - a[i - 1];
s[i][j] = k;
}
}
}
}
n /= 2;
int ans = inf;
_rep(i, 1, n) {
ans = min(ans, dp[i][i + n - 1]);
}
printf("%d\n", ans);
}
return 0;
}