HDU4283:区间DP

HDU4283

题意:

  • 第k出场的嘉宾会有(k-1)*d的不满意度。
  • 所以为了让不满意度最小,改变出场顺序,让嘉宾进入黑屋子。
  • 第一个进入的是最后一个出去(堆栈)。

题解

  • dp[i][j]表示第i到第j个嘉宾都出场了的最优情况。
  • 只有前面的区间才会对后面的区间产生影响,影响为前面区间的人数 * 后面区间的屌丝值总和。所以要保证每个区间最优,再合并。
  • 如果在区间[i,j],i是第k个出场,那么i前面出场的是[i+1,i+k-1],后面出场的是[i+k,j]。这两个小区间都已经算过了,合并即可。
  • 状态转移:dp[i][j] = min(dp[i][j],dp[i+1][i+k-1]+dp[i+k][j]+a[i]*(k-1)+(sum[j]-sum[i+k-1])*k);

代码

#include <bits/stdc++.h>
using namespace std;
int const N = 100 + 10;
int const inf = 0x7f7f7f7f;
int a[N],sum[N],dp[N][N],n;
int main(){
	int T,caser = 0;
	scanf("%d",&T);
	while(T--){
		scanf("%d",&n);
		for(int i=1;i<=n;i++){
			scanf("%d",&a[i]);
			sum[i] = sum[i-1] + a[i];
		}
		for(int i=n;i>=1;i--){  //起始
			for(int j=i+1;j<=n;j++){   //末尾
				dp[i][j] = inf;
				for(int k=1;k<=j-i+1;k++){  //在区间[i,j]为第k个出场
					dp[i][j] = min(dp[i][j],dp[i+1][i+k-1]+dp[i+k][j]+a[i]*(k-1)+(sum[j]-sum[i+k-1])*k);
				}
			}
		}
		printf("Case #%d: %d\n",++caser,dp[1][n]);
	}
	return 0;
}

 

猜你喜欢

转载自blog.csdn.net/weixin_42264485/article/details/89225216