北大ACM poj1011木棍问题总是超时,求修改代码。
#include <iostream>
#include <algorithm>
using namespace std;
const size_t MaxSize = 100;
size_t sticks[MaxSize];
bool bVisited[MaxSize];
size_t oriLen;
size_t minStickLen;
size_t partNum;
size_t counter = 0;
bool Greater(size_t elem1, size_t elem2)
{
return elem1> elem2;
}
bool DFS(size_t curLen, size_t stickNum, size_t start)
{
if(1 == stickNum)
{
return true;
}
//剪枝2
if(curLen < sticks[partNum - 1])
{
return false;
}
//剪枝2
for(size_t i = start; i != partNum; ++i)
{
while((bVisited[i] || sticks[i] > curLen) && i != partNum)
{
++i;
}
if(partNum == i)
{
return false; //没找到
}
if(sticks[i] == curLen)
{
bVisited[i] = true;
if(DFS(oriLen, stickNum - 1, 0))
{
return true; //找到了
}
bVisited[i] = false;
return false; //如此,不能拼出,剩下的更不可能,剪枝3
}
else
{
bVisited[i] = true;
if(DFS(curLen - sticks[i], stickNum, i + 1))
{
return true;
}
bVisited[i] = false;
//剪枝1
while(i != partNum - 1 && sticks[i + 1] == sticks[i])
{
++i;
}
continue;
//剪枝1
}
}
return false;
}
int main()
{
size_t stickNum;
cin >> partNum;
size_t totalLen;
while(partNum != 0)
{
totalLen = 0;
for(size_t i = 0; i != partNum; ++i)
{
cin >> sticks[i];
totalLen += sticks[i];
}
memset(bVisited, 0, MaxSize);
sort(sticks, sticks + partNum, Greater);
for(oriLen = sticks[0]; oriLen <= totalLen; ++oriLen)
{
if(0 == totalLen % oriLen) //最大公约数
{
stickNum = totalLen / oriLen;
memset(bVisited, 0, MaxSize);
if(DFS(oriLen, stickNum, 0))
{
break; //找到
}
}
}
cout << oriLen << endl;
cin >> partNum;
}
return 0;
}
题目地址:http://poj.org/problem?id=1011
被这个题目折磨了两天,看网上的思路,该剪枝的都剪了,代码还是运行超时,怀疑剪枝可能有问题,望大神解答。多谢!
原题如下:
Description
乔治拿来一组等长的木棒,将它们随机地砍断,使得每一节木棍的长度都不超过50个长度单位。然后他又想把这些木棍恢复到为裁截前的状态,但忘记了初始时有多少木棒以及木棒的初始长度。请你设计一个程序,帮助乔治计算木棒的可能最小长度。每一节木棍的长度都用大于零的整数表示。
Input
输入包含多组数据,每组数据包括两行。第一行是一个不超过64的整数,表示砍断之后共有多少节木棍。第二行是截断以后,所得到的各节木棍的长度。在最后一组数据之后,是一个零。
Output
为每组数据,分别输出原始木棒的可能最小长度,每组数据占一行。
Sample Input
9
5 2 1 5 2 1 5 2 1
4
1 2 3 4
0
Sample Output
6
5
[解决办法]
看代码累 说说你的思路
[解决办法]
这题除了硬来有什么好办法么?感觉分2步来也许效果会好一点。
枚举一定范围的约数,这个不用多说了,之后需要找到一种方法能够快速的判断是否无解。
第一步:判断无解。感觉通过Mod 2,3,5,可以将问题转为更小规模的问题,初步估计对于2,3,5,7,可以完全枚举求解。如果小规模无解,则无解,如果小规模有解,大规模未必有解。但如果小规模数据对解的约束很强,那么可以试着在此基础上构造大规模的解。
第二步:构造解,如果小规模数据的解非常多,则跳过,尝试下一个质数,如果解不太多(我也说不出不太多的标准),试着通过可行解构造。
[解决办法]
从大到小找可以整除的数,然后把排序好的棍子来个DeepFirstSearch优先。