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

HDU 1074 Doing Homework:狀壓 DP 最小化扣分總和

     編輯:關於C++

問題建模

有 N ≤ 15 個作業,每個有截止天數 D 和所需天數 C。按順序做作業,完成時間超過截止天數的部分每天扣 1 分。求最小總扣分及字典序最小的作業順序。

狀態定義與轉移

  • dp[mask]:已完成作業集合為 mask 時的最小扣分、總耗時、前驅決策
  • 狀態數 2^15 = 32768,完全可行
  • 轉移:從 mask 嘗試添加未做的作業 i
    • 新耗時 time' = dp[mask].time + C[i]
    • 新扣分 score' = dp[mask].score + max(0, time' - D[i])
    • 若 score' < dp[mask|(1< 或扣分相同時字典序更小,則更新

字典序最小處理

題目保證輸入已按學科名字典序排列。為得到字典序最小的最優解:

  • 狀態轉移時按索引從小到大嘗試添加作業
  • 扣分相等時不更新(保留先到達的字典序更小路徑)
  • 或顯式比較路徑字典序

核心代碼實現

struct State {
    int pre = -1;      // 前驅作業索引
    int time = 0;      // 總耗時
    int score = INF;   // 總扣分
} dp[1<<15];

struct Homework { string name; int d, c; } hw[15];

int main() {
    int T; cin >> T;
    while (T--) {
        int n; cin >> n;
        for (int i = 0; i < n; ++i) cin >> hw[i].name >> hw[i].d >> hw[i].c;
        
        int ALL = 1 << n;
        fill(dp, dp + ALL, State());
        dp[0].score = 0;
        
        for (int mask = 0; mask < ALL; ++mask) {
            if (dp[mask].score == INF) continue;
            for (int i = 0; i < n; ++i) if (!(mask & (1<

關鍵優化與避坑

  • 初始化 dp[0].score = 0,其餘 INF
  • 利用 mask 從小到大遍歷天然保證字典序最小(輸入已排序)
  • 回溯時用 mask ^= (1< 回退
  • 時間複雜度 O(n·2^n),n=15 约 50 萬狀態轉移,極快
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved