首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

ZOJ 2059 The Twin Towers:雙塔等高問題的動態規劃解法

     編輯:關於C++

題目大意

給 N (≤100) 塊晶體,高度為正整數,總高度 < 2000。
將晶體分成兩堆,使兩堆高度相等且盡可能高。
輸出最大等高高度,若不可能輸出 "Sorry"。

狀態定義

dp[i][d]:前 i 塊晶體,兩塔高度差為 d 時,較矮塔的最大高度。
若不可達則為 -1。
初始 dp[0][0] = 0。

狀態轉移

第 i 塊晶體高度 h,三種選擇:

  1. 不使用:dp[i][d] = max(dp[i][d], dp[i-1][d])
  2. 放較高塔:差值增大 → dp[i][d+h] = max(dp[i][d+h], dp[i-1][d])
  3. 放較矮塔:
    • 若 h ≤ d:新差值 d-h,矮塔增高 h → dp[i][d-h] = max(dp[i][d-h], dp[i-1][d] + h)
    • 若 d:新差值 h-d,原矮塔變高塔,新矮塔高度 = 原高塔高度 = dp[i-1][d] + d → dp[i][h-d] = max(dp[i][h-d], dp[i-1][d] + d)

空間優化:滾動陣列

僅依賴 i-1 層,使用兩個 1D 陣列交替:

int dp[2005], ndp[2005];
fill(dp, dp+2005, -1); dp[0] = 0;
for (int i=1; i<=n; ++i) {
    copy(dp, dp+2005, ndp); // 不使用
    for (int d=0; d<=2000; ++d) if (dp[d] != -1) {
        int h = a[i];
        // 放高塔
        if (d+h <= 2000) ndp[d+h] = max(ndp[d+h], dp[d]);
        // 放矮塔
        if (h <= d) ndp[d-h] = max(ndp[d-h], dp[d] + h);
        else ndp[h-d] = max(ndp[h-d], dp[d] + d);
    }
    swap(dp, ndp);
}
int ans = dp[0]; // 差值為 0 時的矮塔高度即為雙塔高度
cout << (ans > 0 ? ans : "Sorry") << "\n";

完整代碼 (含滾動優化)

#include 
using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n;
    while (cin >> n, n > 0) {
        vector a(n+1);
        for (int i=1; i<=n; ++i) cin >> a[i];

        const int MAXH = 2000;
        vector dp(MAXH+1, -1), ndp(MAXH+1, -1);
        dp[0] = 0;

        for (int i=1; i<=n; ++i) {
            ndp = dp; // 不使用
            int h = a[i];
            for (int d=0; d<=MAXH; ++d) if (dp[d] != -1) {
                // 放高塔
                if (d + h <= MAXH) ndp[d+h] = max(ndp[d+h], dp[d]);
                // 放矮塔
                if (h <= d) ndp[d-h] = max(ndp[d-h], dp[d] + h);
                else ndp[h-d] = max(ndp[h-d], dp[d] + d);
            }
            dp.swap(ndp);
        }

        if (dp[0] > 0) cout << dp[0] << "\n";
        else cout << "Sorry\n";
    }
    return 0;
}

複雜度

  • 時間:O(N × MAXH) = 100 × 2000 = 2×10⁵
  • 空間:O(MAXH) = 2001 整數

測試樣例

輸入:
4 11 11 11 11
4 1 11 111 1111
-1

輸出:
22
Sorry

解析:
Case 1:四塊 11,分兩堆各兩塊 → 22
Case 2:總高 1234,無法平分

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved