HDU 4283 You Are the One(區間DP)

原題地址

You Are the One

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3502 Accepted Submission(s): 1614


Problem Description
  The TV shows such as You Are the One has been very popular. In order to meet the need of boys who are still single, TJUT hold the show itself. The show is hold in the Small hall, so it attract a lot of boys and girls. Now there are n boys enrolling in. At the beginning, the n boys stand in a row and go to the stage one by one. However, the director suddenly knows that very boy has a value of diaosi D, if the boy is k-th one go to the stage, the unhappiness of him will be (k-1)*D, because he has to wait for (k-1) people. Luckily, there is a dark room in the Small hall, so the director can put the boy into the dark room temporarily and let the boys behind his go to stage before him. For the dark room is very narrow, the boy who first get into dark room has to leave last. The director wants to change the order of boys by the dark room, so the summary of unhappiness will be least. Can you help him?

Input
  The first line contains a single integer T, the number of test cases. For each case, the first line is n (0 < n <= 100)
  The next n line are n integer D1-Dn means the value of diaosi of boys (0 <= Di <= 100)

Output
  For each test case, output the least summary of unhappiness .

Sample Input
2    5 1 2 3 4 5 5 5 4 3 2 2

Sample Output
Case #1: 20 Case #2: 24

一羣屌絲去參加非誠勿擾,但是他們要排隊上場,他們每個人都有一個憤怒值D,如果他是第k個上場,那麼他的不開心值就會是(k-1)*D。即是說,如果他前面多一個人先上場,那就多D不開心值(不怕屌絲去相親,就怕屌絲玻璃心……)。

但是這裏有一個小黑屋,其實就是個棧。屌絲按順序進入棧,經過調整順序後出來,請問可以調整後得到的所有人不開心值得和最小的是多少?(人善被人欺唄)

思路:

一開始,屌絲們的順序就被定好了,只能經過棧調整。

如果只看第i個人的話,經過棧的調整後,i可以是第一個出來,或者最後一個出來,或者在之間出來。現在假設i是提前了k個人出來的(k可以爲負數,即是推遲k個人後出來),那麼i之前(之後)的k個人就會因爲 i 的位置調整而多等待(少等待)一個人。所以他們的不開心值都會增加(減少)自己對應的D。而 i 會減少(增加)自身的D*k。所以狀態轉移方程也出來了:

dp[i][j]=min(dp[i][j],dp[i+1,i+k-1]+dp[i+k,j]+(k-1)*a[i]+(sum[j]-sum[i+k-1])*k); 

dp[ i ][ j ]爲區間 [ i , j ] 的屌絲經過棧調整後的最小不開心值(忽略 i 前面的人)。

a[ i ]爲第i個人的憤怒值。

sum[ i ]第0~i 個人的憤怒值的和。


下面貼代碼:

#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>

using namespace std;

int sum[111];
int unh[111];
int dp[111][111];

int n;
int deal(int a,int b)
{
    if(a>=b)
    {
        return 0;
    }
    if(dp[a][b]!=-1)
    {
        return dp[a][b];
    }
    dp[a][b]=0x3f3f3f3f;
    //printf("!!!%d %d %d\n",a,b,dp[a][b]);
    for(int k=0;k<b-a+1;k++)
        dp[a][b]=min(dp[a][b],deal(a+1,a+k)+deal(a+k+1,b)+k*unh[a]+(k+1)*(sum[b]-sum[a+k]));

    //printf("!%d %d %d\n",a,b,dp[a][b]);
    return dp[a][b];
}
int main()
{
    int t,cake=1;
    scanf("%d",&t);
    while(t--)
    {
        memset(dp,-1,sizeof(dp));
        scanf("%d",&n);
        sum[0]=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&unh[i]);
            sum[i]=sum[i-1]+unh[i];
        }
        printf("Case #%d: %d\n",cake++,deal(1,n));
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章