您的位置:首页 > 其它

poj 1011 回溯+剪枝 木棒问题

2013-05-10 11:51 323 查看
【题意】:乔治拿来一组等长的木棒,将它们随机地砍断,使得每一节木棍的长度都不超过50个长度单位。然后他又想把这些木棍恢复到为裁截前的状态,但忘记了初始时有多少木棒以及木棒的初始长度。请你设计一个程序,帮助乔治计算木棒的可能最小长度。每一节木棍的长度都用大于零的整数表示。

1.把所有木棍的长度从大到小排列,组合木棒时优先使用长的木棍,这样可以加快组合速度,并且对后面的剪枝有帮助。

2.木棒的长度一定是大于等于最长木棍的长度并且小于等于所有木棍长度的和,这个很容易证明。

3.木棒的长度一定是所有木棍长度的和的约数,这个也很容易证明。

4.在某一个木棒的组合过程中,对于当前的木棍stick[i],如果stick[i-1]没有被组合并且stick[i] == stick[i-1],那么不用考虑stick[i],显然stick[i]最终也不会被组合。

5.如果此次是在尝试第i个木棒的第一段,假设stick[j]为当前可以被使用的最长的木棍,如果此次组合失败,直接退出搜索,即退回到对第i-1个木棒的搜索。试想:失败说明现在使用stick[j]是不可行的,那么以后无论什么时候使用stick[j]都是不可行的,因为以后再处理stick[j]时可使用的木棍一定是当前可使用的木棍的子集,在更多木棍选择的情况下都不能组合成功,那么,在更少木棍选择的情况下一定不能组合成功。

#include <iostream>

#include <algorithm>

using namespace std;

int sticks[64], n, len, num;

bool used[64];

bool compare(int a, int b)

{

return a > b;

}

bool dfs(int cur, int left, int level)

{ //cur: 当前已经计算的木棒编号,left:该段还剩的长度,level:已经成功的木棒数

if(left == 0) {//匹配一根木棒成功

if(level == num-2)

return true;

for(cur = 0; used[cur]; cur++)

;

used[cur] = true;

if(dfs(cur+1, len-sticks[cur], level+1))

return true;

used[cur] = false;

return false;

} else {

if(cur >= n-1)

return false;

for(int i = cur; i < n; i++) {

if(used[i])

continue;

if((sticks[i] == sticks[i-1]) && !used[i-1])

continue;

if(sticks[i] > left)

continue;

used[i] = true;

if(dfs(i, left-sticks[i], level))

return true;

used[i] = false;

}

return false;

}

}

int main()

{

while(cin>>n) {

if(n == 0)

break;

int sum = 0;

for(int i = 0; i < n; i++) {

scanf("%d", &sticks[i]);

sum += sticks[i];

}

sort(sticks, sticks+n, compare); //由大到小排序

bool end = false;

for(len = sticks[0]; len <= sum/2; len++) {

if(sum%len == 0) {

used[0] = true;

num = sum/len;

if(dfs(0, len-sticks[0], 0)) {

end = true;

printf("%d\n", len);

break;

}

used[0] = false;

}

}

if(!end)

printf("%d\n", sum);

memset(used, 0, sizeof(used));

}

//system("pause");

return 0;

}
http://ren.iteye.com/blog/344095 http://www.cppblog.com/y346491470/articles/155318.html http://blog.csdn.net/lyy289065406/article/details/6647960
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: