[編程題]堆磚塊

小易有n塊磚塊,每一塊磚塊有一個高度。小易希望利用這些磚塊堆砌兩座相同高度的塔。爲了讓問題簡單,磚塊堆砌就是簡單的高度相加,某一塊磚只能使用在一座塔中一次。小易現在讓能夠堆砌出來的兩座塔的高度儘量高,小易能否完成呢。
輸入描述:

輸入包括兩行:
第一行爲整數n(1 ≤ n ≤ 50),即一共有n塊磚塊
第二行爲n個整數,表示每一塊磚塊的高度height[i] (1 ≤ height[i] ≤ 500000)

輸出描述:

如果小易能堆砌出兩座高度相同的塔,輸出最高能拼湊的高度,如果不能則輸出-1.
保證答案不大於500000。
示例1
輸入

3
2 3 5
輸出

5

解題思路

動態規劃

假設磚塊分爲A,B兩堆,dp[i][j]中的j表示B-A的長度。
因爲B-A有可能是負的,所以j整體偏移sum個長度,即2*sum+1。
而dp[i][j]的值則表示當A-B的值爲j時,B的最大長度是多少。
dp[i][j] = dp[i-1][j]表示我不用第i塊磚
dp[i][j] = max(dp[i-1][j-h], dp[i-1][j])表示把磚放在A堆。
dp[i][j] = max(dp[i-1][j+h]+h, dp[i-1][j])表示把磚放在B堆。
因爲會爆內存,所以用了滾動數組。下一次結果只依賴於前一次,因而只保存前一次狀態和當前狀態即可。


import java.util.Scanner;

public class Main {

    private static int fun(int[] data) {

        int length = data.length;
        int sum = 0;
        for (int num : data)
            sum += num;
        int[] dp0 = new int[2 * sum + 1];
        int[] dp1 = new int[2 * sum + 1];

        for (int i = 0; i < dp0.length; i++)
            dp0[i] = -1;
        dp0[sum] = 0;

        for (int i = 0; i < length; i++) {
            int h = data[i];
            for (int j = 0; j < 2 * sum + 1; j++) {
                dp1[j] = dp0[j];

                if (j - h >= 0 && dp0[j - h] != -1) {
                    dp1[j] = Math.max(dp0[j - h], dp1[j]);
                }
                if (j + h <= 2 * sum && dp0[j + h] != -1) {
                    dp1[j] = Math.max(dp0[j + h] + h, dp1[j]);
                }
            }
            int[] temp = dp0;
            dp0 = dp1;
            dp1 = temp;
        }
        return dp0[sum] == 0 ? -1 : dp0[sum];

    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int[] data = new int[n];
        for (int i = 0; i < n; i++)
            data[i] = sc.nextInt();
        System.out.println(fun(data));
    }
}
發佈了98 篇原創文章 · 獲贊 13 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章