题意:
n个人按顺序排队,从排头开始每个人可以选择去小黑屋或者直接上台。小黑屋类似于栈,先进后出。小黑屋里的人上台的选择权优先于后面的人。每个人有一个值Di,若第i个人第k个上台,那么焦躁值为(k - 1) * Di。问总焦躁值的最小值。
题解:
1.dp[i][j]表示[i , j]区间的总焦躁值的最小值。
2.[i,j]的第i个人可以选择第k个上场(i <= k <= j),注意如果[i,j]区间的第1个人想要第k个出场那么(i,k]一定比i先上场!!!!!!
dp[i][j] = min(dp[i][j] , dp[i + 1][k] + a[i] * (k - i) + dp[k + 1][j] + (k - i + 1) * (sum[j] - sum[k]))。i + 1 <= k <= j - 1。
3.注意初始化。
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 105
#define inf 0x3f3f3f3f
using namespace std ;
int main()
{
int t , n ;
int i , j , d , k , p ;
int a[N] , dp[N][N] ;
int sum[N] ;
scanf("%d" , &t) ;
for(p = 1 ; p <= t ; p ++)
{
scanf("%d" , &n) ;
for(i = 1 ; i <= n ; i ++)
scanf("%d" , &a[i]) ;
memset(dp , inf , sizeof(dp)) ;
memset(sum , 0 , sizeof(sum)) ;
for(i = 1 ; i <= n ; i ++)
dp[i][i] = 0 ;
for(i = 1 ; i <= n ; i ++)
sum[i] = sum[i - 1] + a[i] ;
for(i = 1 ; i <= n - 1 ; i ++)
dp[i][i + 1] = min(a[i] , a[i + 1]) ;
for(d = 2 ; d <= n - 1 ; d ++)
for(i = 1 ; i + d <= n ; i ++)
{
j = i + d ;
dp[i][j] = dp[i + 1][j] + sum[j] - sum[i] ;
for(k = i + 1 ; k <= j - 1 ; k ++)
dp[i][j] = min(dp[i][j] , dp[i + 1][k] + a[i] * (k - i) + dp[k + 1][j] + (k - i + 1) * (sum[j] - sum[k])) ;
dp[i][j] = min(dp[i][j] , dp[i + 1][j] + a[i] * (j - i)) ;
}
printf("Case #%d: %d\n" , p , dp[1][n]) ;
}
}