hdu 4283 区间dp 栈的特性

题意:

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

猜你喜欢

转载自blog.csdn.net/Irving0323/article/details/87937257