HDU4283(区间dp)

题目大意:一些屌丝排队进场,第k个进场的人后又k-1*a[i]的愤怒值,为了得到最小的愤怒值,可以利用一个栈来调整顺序,第i个人进栈可以让第i+1个人先行入场,对于栈里的元素必须是后进先出,问如何合理利用栈来以得到最小的愤怒值。
解题思路:我们用dp[i][j]表示区间i~j之中的元素可得到的最小的愤怒值。对于i~j中的元素i我们然他第k个入场,那么其后面的k-1个元素就要先行入场,
          这是问题就变成了dp[i+1][i+k-1]和dp[i+k][j], 对于第i个元素的愤怒值为:(k-1)*a[i],而第i+k~j的愤怒值要加上k*(sum[j]-sum[i+1-1]);
          最后dp[1][n]就是答案
以上摘自https://blog.csdn.net/lvshubao1314/article/details/44672559 

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#define inf 0x3f3f3f3f
using namespace std;
int s[105],sum[105];
int dp[105][105];
int main()
{
	//freopen("t.txt","r",stdin);
	int T,n;
	scanf("%d",&T);
	for(int ca=1;ca<=T;ca++)
	{
		printf("Case #%d: ",ca);
		scanf("%d",&n);
		//cout<<n<<"*"<<endl;
		int p=0;
		for(int i=0;i<n;i++)
		{
			scanf("%d",&s[i]);
			//cout<<s[i]<<endl;
			sum[i]=s[i]+p;
			p=sum[i];
		}
		memset(dp,0,sizeof(dp));
		for(int i=0;i<n;i++)
		{
			for(int j=i+1;j<n;j++)
			{
				dp[i][j]=inf;
			}
		}
		for(int t=1;t<n;t++)
		{
			for(int i=0;i+t<n;i++)
			{
				int j=i+t;
				for(int k=i;k<=j;k++)
				{
					dp[i][j]=min(dp[i][j],dp[i+1][k]+dp[k+1][j]+(k-i)*s[i]+(k-i+1)*(sum[j]-sum[k]));
				}
			}
		}
		printf("%d\n",dp[0][n-1]);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_39861441/article/details/88591264