hdu4283You Are the One 区间dp

//n个人,每个人有屌丝系数di
//对于第i个人第j个出来,那么其不高兴值为(j-1)*di
//可以用一个栈来控制这些人的出去顺序
//问其怎样安排使得所有人的不高兴值最小为多少
//用dp[i][j]表示从i开始的长度为j的区间的最小不高兴值
//dp[i][j] = min(dp[i][j] ,min(dp[i][k] + dp[i+k][j-k] + k*sum[i+k][i+j-1] , dp[i+k][j-k] + (j-k)*sum[i][i+k-1] + s[i+k-1][k])) ;
//sum[i][j] 表示区间[i,j]的所有的数之和
//s[i][j] 表示区间的最后一位是i的长度为j的区间从后往前的输出的最小不高兴值
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std ;
const int maxn = 110 ;
const int inf = 0x7fffffff ;
int dp[maxn][maxn] ;
int sum[maxn][maxn] ;
int s[maxn][maxn] ;
int a[maxn] ;
int main()
{
    int t ;
    int cas = 0 ;
    scanf("%d" , &t) ;
    while(t--)
    {
        int n ;
        scanf("%d" , &n) ;
        memset(sum , 0 , sizeof(sum)) ;
        memset(s , 0 , sizeof(s)) ; 
        for(int i = 1;i <= n;i++)
        {
            scanf("%d" , &a[i]) ;
            for(int j = 1;j <= i;j++)
              for(int k = i;k <= n;k++)
              sum[j][k] += a[i] ;
        }
        
        for(int i = 1;i <= n;i++)
          for(int j = 1;j <= i;j++)
              for(int k = i;k > i - j;k--)
              s[i][j] += (i-k)*a[k] ;
        
        for(int i = 1;i <= n;i++)
        dp[i][1] = 0 ;
        for(int j = 2;j <= n;j++)
           for(int i = 1;i <= n-j+1;i++)
           {
               dp[i][j] = inf ;
               for(int k = 1;k < j;k++)
               {
                   int tmp = min(dp[i][k] + dp[i+k][j-k] + k*sum[i+k][i+j-1] , dp[i+k][j-k] + (j-k)*sum[i][i+k-1] + s[i+k-1][k]) ;
                   dp[i][j] = min(dp[i][j] ,tmp) ;
               }
           }
        printf("Case #%d: " , ++cas) ;
        cout<<dp[1][n]<<endl;
    }
    return  0 ;
}

你可能感兴趣的:(hdu4283You Are the One 区间dp)