搜尋_DFS_迭代加深_POJ2248_Addition Chains
阿新 • • 發佈:2018-11-19
思路分析:
可通過列舉序列的前i - 1個數兩兩之和確定第i個數的值, 考慮到100 = 50 + 50, 50 = 25 + 25, 25 = 13 + 12, 13 = 7 + 6, 7 = 4 + 3. 4 = 2 + 2, 3 = 1 + 2, 因此當n <= 100時, 最小的m值不會超過12, 因此考慮使用迭代加深DFS並使用如下剪枝策略
(1)確定第i個數時避免考察某個和多次
(2)如果已經計算出一個當前的最優解s, 且當前結點比s少一個數, 設當前結點最後一個數為k, 且k + k >= n, 那麼立即回溯
(3)從較大的和開始列舉
基於上述剪枝策略給出如下AC程式碼:
//POJ2248_Addition Chains #include <iostream> #include <cstdio> #include <cstring> #include <vector> using namespace std; const int NIL = 0x3f3f3f3f; int n, deep, ans; vector<int> path, ansv; void dfs(){ if(path.size() >= ans || ans != NIL && (path.size() >= ans - 1 && path.back() * 2 <= n)) return; if(path.size() == deep){ if(path.back() == n) ans = path.size(), ansv = path; return; } if(path.back() == n){ ans = path.size(), ansv = path; return; } bool used[101]; memset(used, false, sizeof(used)); for(int i = path.size() - 1; i >= 0; --i) if(path[i] * 2 <= path.back()) return; else for(int j = i; j >= 0; --j) if(path[i] + path[j] > n || used[path[i] + path[j]]) continue; else used[path[i] + path[j]] = true, path.push_back(path[i] + path[j]) , dfs(), path.pop_back(); } int main(){ while(scanf("%d", &n), n){ ans = NIL, deep = 0; while(ans == NIL) ++deep, ansv.clear(), path.clear(), path.push_back(1), dfs(); for(int i = 0; i < ansv.size(); ++i) cout << ansv[i] << " "; cout << endl; } return 0; }