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

题意:n个人要入场选秀,给定他们的屌丝值D,可以用一个栈来调整顺序,第i个人第j个入场的不开心值为Di*(j-1),问所有人不开心值的总和最小是多少?(n<=100)

这明显是区间DP的套路题,对于一个区间[L,R],先将L推进栈里,枚举第L个人第k个进场,那么第一个入场的人可以推出为L+k-1,那么就分成了{L},[L+1,L+k-1],[L+k,R]三个子区间,其中L的不开心值为D[L]*(k-1),[L+1,L+k-1]的不开心值为dp[L+1][L+k-1],而对于[L+k,R]的不开心值,由于这些人要等k个人,所以不开心值要整体加上k*(S[R]-S[L+k-1]),最终的不开心值为k*(S[R]-S[L+k-1])+dp[L+k][R],可得状态转移方程如下:

dp[L][R]=min{D[L]*(k-1)+dp[L+1][L+k-1]+k*(S[R]-S[L+k-1])+dp[L+k][R]}

#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define FOR(i,x,y) for(int i=(x);i<=(y);i++)
#define DOR(i,x,y) for(int i=(x);i>=(y);i--)
using namespace std;
int A[103],S[103];
int dp[103][103];

int main()
{
	int kase,n;
	scanf("%d",&kase);
	FOR(k,1,kase)
	{
		scanf("%d",&n);
		S[0]=0;
		FOR(i,1,n)
		{
		    scanf("%d",&A[i]);
		    S[i]=S[i-1]+A[i];
		}
		FOR(l,1,n)  //区间长度为l
		    FOR(L,1,n-l+1)
			{
			    int R=L+l-1;
				dp[L][R]=1e9;
				FOR(k,1,l)    //枚举L是第几个入场的
				    dp[L][R]=min(dp[L][R],A[L]*(k-1)+dp[L+1][L+k-1]+dp[L+k][R]+k*(S[R]-S[L+k-1]));
			}
		printf("Case #%d: %d\n",k,dp[1][n]);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/paulliant/article/details/80189643