您的位置:首页 > 其它

POJ 1011: Sticks

2015-03-12 04:51 344 查看
解题要点: DFS + 剪枝.

这道题可以通过 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;
}
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: