Monkey Party HDU - 3506(区间DP,四边形不等式加速)

Monkey Party

 题目链接:HDU - 3506

题意:n个猴子围成一圈,猴王每次将两个猴子相互介绍认识,每次介绍时,两个猴子原来认识的也就都认识了,每次介绍花费时间时两个猴子所认识的的权值之和, 每次只能相邻猴子介绍,问最少花费时间;

思路:其实就是环形的合并石子,一模一样,就是把石子改成了猴子,n堆石子扩展为2n堆合并,最后找合并长度时n的;

然后思如泉涌就写完了,,,,,T了!!!!一看数据,恍然大明白,1000个猴,复杂度O(n^3),T是没跑了;

咋办哪!!!!!!!

在区间DP中有个优化,四边形不等式加速,优化后是O(n^2)的复杂度;

令s[i][j]=max( k  |   min(dp[i][j])(i<=k<=j));这个式子是不是很懵逼?表示使dp[i][j]最小的最大k;

则dp[i][j]=min(dp[i][k]+dp[k+1][j]+sum[i][j]  |   s[i][j-1] <=k<= s[i+1][j]);

虽然还是三层循环,但是复杂度是O(n^2)的;

证明我还真不会~~~

欲知详情,请百度:动态规划加速原理之四边形不等式

赵爽老师写的,还算不错,虽然没看懂证明,,,,但是会简单运用了,,,,数学还是硬伤啊!!!!

#include <bits/stdc++.h>
#define INF 0x7f7f7f7f
using namespace std;
typedef long long ll;
ll t[2100], dp[2100][2100], s[2100][2100], sum[2100];
int main(){
	int n;
	while(~scanf("%d", &n)){
		memset(dp, INF, sizeof(dp));
		for(int i=1; i<=n; i++){
			scanf("%d", &t[i]);
			t[i+n]=t[i];
		}
		sum[0]=0;
		for(int i=1; i<=2*n; i++){
			sum[i]=sum[i-1]+t[i];
			dp[i][i]=0;
			s[i][i]=i;
		}
		for(int len=2; len<=n; len++){
			for(int i=1; i+len-1<=2*n; i++){
				int j=i+len-1;
				for(int k=s[i][j-1]; k<=s[i+1][j]; k++){
					ll temp=dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1];
					if(dp[i][j]>=temp){
						dp[i][j]=temp;
						s[i][j]=k;
					}
				}
			}
		}
		ll ans=INF;
		for(int i=1; i<=n; i++){
			ans=min(ans, dp[i][i+n-1]);
		}
		printf("%d\n", ans);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Sirius_han/article/details/81335987
今日推荐