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

POJ 1040 Transportation:火車售票最大收益的 DFS + 剪枝

     編輯:關於C++

問題描述

火車從站 0 開往站 m,容量 n。有 p ≤ 22 個訂單,每單含 start, end, num。接受訂單則收益 (end-start)*num。車上任意時刻乘客數不能超過容量。求最大總收益。

解法:狀態空間搜索(DFS)

訂單數極小(≤22),可對每個訂單決策「接受/拒絕」。用 people[i] 記錄區間 [i-1, i] 上的乘客數。接受訂單前檢查沿途所有區段是否超載,超載則剪枝。按起點、終點排序訂單可提高剪枝效率。

關鍵代碼

struct Order { int s, e, p; } ord[30];
int cap, stations, orders;
int load[30]; // load[i] = 區段 i-1→i 的乘客數
int best;

void dfs(int idx, int money) {
    if (idx == orders) { best = max(best, money); return; }
    // 嘗試接受
    bool ok = true;
    for (int i = ord[idx].s + 1; i <= ord[idx].e; i++)
        if (load[i] + ord[idx].p > cap) { ok = false; break; }
    if (ok) {
        for (int i = ord[idx].s + 1; i <= ord[idx].e; i++) load[i] += ord[idx].p;
        dfs(idx+1, money + (ord[idx].e - ord[idx].s) * ord[idx].p);
        for (int i = ord[idx].s + 1; i <= ord[idx].e; i++) load[i] -= ord[idx].p;
    }
    // 拒絕
    dfs(idx+1, money);
}

int main() {
    while (scanf("%d%d%d",&cap,&stations,&orders), cap||stations||orders) {
        for (int i=0;i

剪枝優化

  • 排序:先按起點升序,再按終點升序,使區間盡早結束,釋放容量。
  • 可加入「剩餘訂單最大潛在收益」上界剪枝(預計算後綴和)。
  • 因 p ≤ 22,狀態數 2^22 ≈ 400萬,配合剪枝極快。

總結

POJ 1040 是典型的「小規模決策問題用 DFS 暴力搜索 + 剪枝」的教科書例題。關鍵在於正確建模區段載客量、排序優化搜索順序、以及回溯時恢復狀態。掌握此模板,可解決大量資源分配、區間調度類問題。

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