POJ 1011: Sticks
2015-03-12 04:51
344 查看
解题要点: DFS + 剪枝.
这道题可以通过 DFS 完成, 但实践证明暴力搜索会导致 TLE, 因此必须剪枝. 具体思路如下:
获得断棍长度阵列后, 立即降序排列. 因为木棍越长, 约束就越大, 可以使剪枝处最接近根部.
每根木棍的长度必定介于最长断棍和木棍总长度之间. 剪枝.
每根木棍的长度必定能够整除木棍的总长度. 剪枝.
搜索时若发现某根断棍不符合要求, 那么跳过之后与其等长的断棍. 剪枝.
组合出的每根木棍, 其包含的第一根短棍的左侧不会有未参与组合的木棍, 因此无需执行无谓的循环. 剪枝.
在已经成功组合了一部分木棍的情况下, 若剩下的断棍无法成功组合为木棍, 则立即返回上一层. 剪枝.
上述剪枝方案中, 5 和 6 对算法效率的影响最大, 需要着重注意.
(尽管我已先行完成了代码并 AC, 但在写这篇博客时, 我发现了 Shawon 在其博客里已经展开过相当精辟的讨论. 拜读之后, 我觉得自己没必要重新发明一遍车轱辘了, 因此直接摘录了 Shawon 的讨论, 之后仅做了一些文字方面的修改以符合我自己的语言风格. 原文地址: /article/1762109.html)
代码如下:
这道题可以通过 DFS 完成, 但实践证明暴力搜索会导致 TLE, 因此必须剪枝. 具体思路如下:
获得断棍长度阵列后, 立即降序排列. 因为木棍越长, 约束就越大, 可以使剪枝处最接近根部.
每根木棍的长度必定介于最长断棍和木棍总长度之间. 剪枝.
每根木棍的长度必定能够整除木棍的总长度. 剪枝.
搜索时若发现某根断棍不符合要求, 那么跳过之后与其等长的断棍. 剪枝.
组合出的每根木棍, 其包含的第一根短棍的左侧不会有未参与组合的木棍, 因此无需执行无谓的循环. 剪枝.
在已经成功组合了一部分木棍的情况下, 若剩下的断棍无法成功组合为木棍, 则立即返回上一层. 剪枝.
上述剪枝方案中, 5 和 6 对算法效率的影响最大, 需要着重注意.
(尽管我已先行完成了代码并 AC, 但在写这篇博客时, 我发现了 Shawon 在其博客里已经展开过相当精辟的讨论. 拜读之后, 我觉得自己没必要重新发明一遍车轱辘了, 因此直接摘录了 Shawon 的讨论, 之后仅做了一些文字方面的修改以符合我自己的语言风格. 原文地址: /article/1762109.html)
代码如下:
#include <iostream> #include <vector> #include <set> #include <bitset> #include <algorithm> #include <cmath> using namespace std; void calcFactors( set<int>& fac, int num, int min = 1 ) { int m = sqrt( num ) + 1; int tmp; for( int i = 1; i < m; ++i ) { if( num % i == 0 ) { if( i >= min ) { fac.insert( i ); } tmp = num / i; if( tmp >= min ) { fac.insert( tmp ); } } } } bool validate( const int& length, int remain, int beg, const vector<int>& sticks, bitset<64>& flags ) { for( int i = beg; i < sticks.size(); ++i ) { if( flags[i] || sticks[i] > remain ) { continue; } flags.set( i ); if( sticks[i] == remain ) { if( flags.count() == sticks.size() || validate( length, length, 1, sticks, flags ) ) { return true; } } else { if( validate( length, remain - sticks[i], i + 1, sticks, flags ) ) { return true; } } flags.reset( i ); if( length == remain ) { break; } while( i < sticks.size() - 1 && sticks[i] == sticks[i + 1] ) { ++i; } } return false; } int main() { int n; while( cin >> n && n != 0 ) { vector<int> sticks; int total = 0; int tmp; while( n-- != 0 ) { cin >> tmp; sticks.push_back( tmp ); total += tmp; } sort( sticks.begin(), sticks.end(), greater<int>() ); set<int> fac; calcFactors( fac, total, *( sticks.begin() ) ); for( set<int>::const_iterator pFac = fac.begin(); pFac != fac.end(); ++pFac ) { bitset<64> flags; if( validate( *pFac, *pFac, 0, sticks, flags ) ) { cout << *pFac << endl; break; } } } }
相关文章推荐
- POJ 1011 Sticks 强大的剪枝
- hdu 1455 poj 1011 sticks
- [深搜+剪枝] POJ - 1011 Sticks
- poj 1011 Sticks 深度搜索+(剪枝)
- POJ 1011 Sticks
- poj 1011 Sticks【dfs】
- POJ 1011 Sticks
- [POJ][1011]Sticks
- DFS POJ 1011 Sticks
- hdu1455 && poj1011 Sticks(深度优先搜索 DFS 经典剪枝 详解)
- poj 1011 Sticks
- POJ_1011_Sticks
- poj 1011 Sticks
- POJ 1011 Sticks
- poj 1011 Sticks - 经典DFS
- Sticks(poj 1011)
- poj 1011 Sticks
- poj 1011 Sticks ,剪枝神题
- POJ 1011 Sticks
- poj 1011 Sticks(dfs+剪枝)