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;
}