You Are the One HDU - 4283 (区间DP)

You Are the One

 题目链接:HDU - 4283 

题意:一群屌丝要上台表演节目, 由于舞台太小,每次只允许一个人表演,所以屌丝们在后台排起了长长的队,每位屌丝还有个屌丝值Di,轮不到他他就难受,不高兴,如果前边有k个人,他的怒气值就为Di*k;后台呢,还有个小黑屋,可以临时把一个屌丝值小的屌丝关进去,让后边的人先上台(欺负老实人啊~~~),小黑屋里可以关任意数量的人,但是先进去的要最后出来;问通过小黑屋安排后怒气和的最小值;

思考了大半天没整明白,还想着贪心做,结果怎么也贪不对,搜了搜题解都是区间DP,也没整懂题解的意思;按题解的思路又怼了半天,终于怼出来了;

令sum[i]为前i个屌丝的屌丝值的和;

只考虑区间[L, R],从L开始上台,设最优解为dp[L][R];

在区间[L, R]中,如果开头的L第K个上台,那么L一定是在区间[L+1, L+K-1]的后边上台,此时区间[L+1, L+K-1]的最优解是dp[L+1, L+K-1];L的怒气值为D[L]*(K-1),L是第K个上台,那么他前边就有K-1个人;再看L之后上台的是谁,是区间[L+K][R],如果该区间是一开始就上台的话,最优解是dp[L+K][R],但是现在前边多了K个人,所以每个人都增加了自身屌丝值K倍的怒气:K*D[L+K]+K*D[L+K+1]+···+K*D[R-1]+K*[R]=K*(sum[R]-sum[L+K-1]);

到此为止,当L第K个上台的时候dp[L][R]=dp[L+1][L+K-1]+D[L]*k+dp[L+K][R]+K*(sum[R]-sum[L+K-1]);

K就是从1~R-L+1取值;

所以总的状态转移方程为:dp[i][j]=min(dp[i+1][i+k-1]+D[i]*k+dp[i+k][j]+k*(sum[j]-sum[i+k-1])    |     1<=k<=j-i+1);

#include <bits/stdc++.h>
#define INF 0x7f7f7f7f
using namespace std;
int D[110], dp[110][110], sum[110];
int main(){
	int T, cas=0;
	scanf("%d", &T);
	while(T--){
		int n;
		scanf("%d", &n);
		sum[0]=0;
		memset(dp, 0, sizeof(dp));
		for(int i=1; i<=n; i++){
			scanf("%d", &D[i]);
			sum[i]=D[i]+sum[i-1];
		}
		for(int len=2; len<=n; len++){
			for(int i=0; i+len-1<=n; i++){
				int j=i+len-1;
				int temp=INF;
				for(int k=1; k<=len; k++){
					temp=min(temp, dp[i+1][i+k-1]+D[i]*(k-1)+dp[i+k][j]+(sum[j]-sum[i+k-1])*k);
				}
				dp[i][j]=temp;
			}
		}
		printf("Case #%d: %d\n", ++cas, dp[1][n]);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Sirius_han/article/details/81347265