搭建雙塔-P1037

2001年9月11日,一場突發的災難將紐約世界貿易中心大廈夷爲平地,Mr. F曾親眼目睹了這次災難。爲了紀念“9?11”事件,Mr. F決定自己用水晶來搭建一座雙塔。
Mr. F有N塊水晶,每塊水晶有一個高度,他想用這N塊水晶搭建兩座有同樣高度的塔,使他們成爲一座雙塔,Mr. F可以從這N塊水晶中任取M(1≤M≤N)塊來搭建。但是他不知道能否使兩座塔有同樣的高度,也不知道如果能搭建成一座雙塔,這座雙塔的最大高度是多少。所以他來請你幫忙。
給定水晶的數量N(1≤N≤100)和每塊水晶的高度Hi(N塊水晶高度的總和不超過2000),你的任務是判斷Mr. F能否用這些水晶搭建成一座雙塔(兩座塔有同樣的高度),如果能,則輸出所能搭建的雙塔的最大高度,否則輸出“Impossible”。
格式
輸入格式

輸入的第一行爲一個數N,表示水晶的數量。第二行爲N個數,第i個數表示第i個水晶的高度。
輸出格式

輸出僅包含一行,如果能搭成一座雙塔,則輸出雙塔的最大高度,否則輸出一個字符串“Impossible”。
輸入:
5
1 3 4 5 2
輸出:
7

這裏借用了別人的解釋:http://m.blog.csdn.net/blog/ctxdecs/25882407

dp[i][j]表示前i個高度差爲j的矮塔(或者高塔)的高度,這裏以矮塔爲例(高塔看代碼),

分爲4種情況,

  1. 第i個塔不取 dp[i][j] = dp[i-1][j];

第i個塔取

2.放在矮塔上但矮塔還是矮塔. dp[i][j] = max(dp[i][j], dp[i-1][j+num[i]] + num[i]);

解釋一下dp[i-1][j+num[i]]+num[i] , 當前差值爲j,就是放在矮塔上,以前的差值就是j+num[i]

所以dp[i-1][j+num[i]]表示以前的矮塔,加上num[i]後就是現在的矮塔的高度

3.放在矮塔上但矮塔變爲高塔. dp[i][j] = max(dp[i][j], dp[i-1][num[i]-j] + num[i]-j),前提是num[i]>=j

解釋一下:當前差值爲j就是矮塔放上num[i]變爲高塔之後與以前高塔的差值,

dp[i-1][num[i]-j],其中num[i]-j表示矮塔未放num[i]時兩塔之間的差值,dp表示以前矮塔的高度

dp[i-1][num[i]-j]+num[i]-j實際上爲以前高塔的高度(因爲現在變爲矮塔了).

4.放在高塔上,dp[i][j] = max(dp[i][j], dp[i-1][j-num[i]]),(前提j>=num[i]),

dp[i-1][j-num[i]]表示以前矮塔的高度,現在差值爲j是因爲+num[i],那麼以前差值就是j-num[i].

#include <stdio.h>
#include <string.h>

int dp[201][2001];
int num[201];

int max(int a, int b)
{
    return a>b?a:b;
}

int main()
{
    int sum[201] = {
        0
    };
    int n;
    scanf("%d", &n);
    for (int i=1; i<=n; ++i)
    {
        scanf("%d", &num[i]);
        sum[i] = sum[i-1] + num[i];

    }
    memset(dp, 0x8f, sizeof(dp));
    dp[0][0] = 0;
    for (int i=1; i<=n; ++i)
    {
        for (int j=sum[i]; j>=0; --j)
        {
            dp[i][j] = max(dp[i-1][j], dp[i-1][j+num[i]]);// 不放, 放矮塔還是矮塔
            if (j>=num[i])
            {
                // 放高塔
                dp[i][j] = max(dp[i][j], dp[i-1][j-num[i]]+num[i]);
            }
            else
            {
                // 放矮塔變高塔
                dp[i][j] = max(dp[i][j], dp[i-1][num[i]-j]+j);
            }
        }/*

        for (int j = sum[i]; j >= 0; j--)
        {
            dp[i][j] = max(dp[i-1][j], dp[i-1][j+num[i]] + num[i]);
            if (j >= num[i])
            {
                dp[i][j] = max(dp[i][j], dp[i-1][j-num[i]]);
            }
            else
            {
                dp[i][j] = max(dp[i][j], dp[i-1][num[i]-j] + num[i]-j);
            }
        }*/
    }

    int ans = dp[n][0];
    if (ans > 0)
        printf("%d\n", ans);
    else
        puts("Impossible");

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