HDU4283.You Are the One(区间DP)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4283
题意:给出n个人,第k个上场的人有(K-1)*D的不满度,有一个小黑屋可以用来放人(类似于堆栈,先进小黑屋的后出)来调整上台顺序,问最小的不满度。
解题思路:区间DP
求出前i个值的总和 sum[i]=d1+d2+…+di
dp[i][j]表示第i个人到第j个人之间的最小不满意度(只考虑i到j这些人)
具体解释看注释就可以

for(int k=1;k<=n-1;k++){
			for(int i=1;i+k<=n;i++){
				for(int j=i;j<=i+k;j++){
				//整个整体都是只放在i到i+k中考虑的
				//第i个人放在第j个位置出场
				//那么在i到i+k这些人中,第i+1到j个人正常输出最小不满意度dp[i+1][j]就可以
				//第j个位置留给i,不满意度为a[i]*(j-1)
				//后i+k-j个人输出最小不满意度dp[j+1][i+k]但注意这个是相对于原来的j+1到i+k,现在放在的是i到i+k这个整体中,所以要整体加上(sum[i+k]-sum[j])*(j-i+1)
					dp[i][i+k]=min(dp[i][i+k],a[i]*(j-i)+dp[i+1][j]+dp[j+1][i+k]+(sum[i+k]-sum[j])*(j-i+1));
				}
			}
		}
#include<iostream>
#include<cstdio>
#include<string.h>
using namespace std;
#define inf 1e9
int t;
int n;
int a[110];
int dp[110][110];
int sum[110];
int min(int a,int b){
	return a<b? a:b;
}
int main(){
	cin>>t;
	int c=0;
	while(t--){
		c++;
		memset(dp,0,sizeof(dp));
		memset(sum,0,sizeof(sum));
		cin>>n;
		for(int i=1;i<=n;i++){
			scanf("%d",&a[i]);
			sum[i]=sum[i-1]+a[i];
		}
		for(int i=1;i<=n;i++)
			for(int j=i+1;j<=n;j++)
				dp[i][j]=inf;
		for(int k=1;k<=n-1;k++){
			for(int i=1;i+k<=n;i++){
				for(int j=i;j<=i+k;j++){
					dp[i][i+k]=min(dp[i][i+k],a[i]*(j-i)+dp[i+1][j]+dp[j+1][i+k]+(sum[i+k]-sum[j])*(j-i+1));
				}
			}
		}
		printf("Case #%d: %d\n",c,dp[1][n]);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/littlegoldgold/article/details/107348527