POJ1011 DFS+剪枝
2017-09-03 19:13
375 查看
题意
乔治有一堆相同长度的木棍,随意切割。这时他想要将这些切割后的短棍复原成若干条相同长度的木棍。求复原后木棍的最小长度。
思路:
1、答案只可能是木棍总长的约数,且不小于最长短棍的长度,则可将问题转化为熟悉的求和问题。
2、将长度降序排列,有利于剪枝。
3、具体剪枝看代码注释。
反思
1、没有想到第一点。
2、剪枝还需强化。
代码
乔治有一堆相同长度的木棍,随意切割。这时他想要将这些切割后的短棍复原成若干条相同长度的木棍。求复原后木棍的最小长度。
思路:
1、答案只可能是木棍总长的约数,且不小于最长短棍的长度,则可将问题转化为熟悉的求和问题。
2、将长度降序排列,有利于剪枝。
3、具体剪枝看代码注释。
反思
1、没有想到第一点。
2、剪枝还需强化。
代码
#include <cstdio> #include <queue> #include <algorithm> #include <cstring> #include <iostream> using namespace std; const int MAXN = 70; priority_queue<int, vector<int>, greater<int> > divisor; int n, total, _max; int stick[MAXN], add[MAXN]; bool vis[MAXN]; bool cmp(int a, int b) { return a > b; } void Find() { for(int i = 1; i * i <= total; i++) { if(total % i == 0) { if(i >= _max) divisor.push(i); if(i != (total/i) && (total/i) >= _max) divisor.push(total/i); } } } void Add()//剪枝1 利用后缀和 { add = stick ; for(int i = n - 1; i >= 1; i--) { add[i] = add[i + 1] + stick[i]; } } bool DFS(int target, int tempTarget, int pos, int used) { vis[pos] = true; if(tempTarget == 0 && used == n) { printf("%d\n", target); return true; } if(tempTarget == 0 && used != n) { if(DFS(target, target, 0, used)) return true; else return false; } if(pos == 0)//剪枝2 如果是重新拼一根新的木棍,第一根可用且最长的短棍无法DFS成功,这根便永远也无法用上了。 { for(int i = 1; i <= n; i++) { if(tempTarget >= stick[i] && !vis[i] && tempTarget <= add[i]) { if(DFS(target, tempTarget - stick[i], i, used + 1)) return true; else { vis[i] = false; return false; } } } } else { for(int i = pos + 1; i <= n; i++) { if(tempTarget >= stick[i] && !vis[i] && tempTarget <= add[i]) { if(!vis[i - 1] && stick[i] == stick[i - 1]) continue;//剪枝3 最重要的剪枝,防止在同一层面进行无意义的重复搜索 if(DFS(target, tempTarget - stick[i], i, used + 1)) return true; else { vis[i] = false; } } } } return false; } int main() { while(scanf("%d", &n) && n) { total = 0; memset(vis, false, sizeof(vis)); while(!divisor.empty()) divisor.pop(); for(int i = 1; i <= n; i++) { scanf("%d", &stick[i]); total += stick[i]; } sort(stick + 1, stick + 1 + n, cmp); _max = stick[1]; Find(); Add(); while(!divisor.empty()) { if(DFS(divisor.top(), divisor.top(), 0, 0)) break; else { divisor.pop(); } } } return 0; }
相关文章推荐
- poj 1011 Sticks(经典深搜dfs+剪枝)
- poj1011 Sticks(dfs+剪枝)
- POJ 1011 Sticks 经典的dfs+剪枝
- poj1011——Sticks(dfs+剪枝)
- poj(1011)——Sticks(经典的dfs+剪枝)
- poj1011 Sticks(dfs+剪枝)
- poj 1011 :Sticks (dfs+剪枝)
- POJ 1011 Sticks 经典的DFS+剪枝
- 数据结构(四)递归与回溯——POJ-1011 dfs+剪枝
- POJ 1011 Sticks(dfs+剪枝)
- poj 1011 :Sticks (dfs+剪枝)
- poj 1011 Sticks -----dfs+剪枝
- poj 1011 Sticks(dfs+剪枝)
- poj(1011)——Sticks(经典的dfs+剪枝)
- poj 1011 Sticks(dfs+剪枝)
- POJ1011 选木棒 DFS+剪枝
- POJ 1011 Sticks(dfs+剪枝)
- poj1011 木棒 dfs+剪枝
- TLE: poj 1011 Sticks
- POJ 1011/DFS:子集划分