题目也挺难懂的,要仔细审题,其实就是一句话搞定的意思:把一组数组合成所有数值相等的一组新的数列。
看她题目说了一大堆:
Description
George took sticks of the same length and cut them randomly until all parts became at most 50 units long. Now he wants to return sticks to the original state, but he forgot how many sticks he had originally and how long they were originally. Please help him and design a program which computes the smallest possible original length of those sticks. All lengths expressed in units are integers greater than zero.
Input
The input contains blocks of 2 lines. The first line contains the number of sticks parts after cutting, there are at most 64 sticks. The second line contains the lengths of those parts separated by the space. The last line of the file contains zero.
Output
The output should contains the smallest possible length of original sticks, one per line.
Sample Input
9 5 2 1 5 2 1 5 2 1 4 1 2 3 4 0
Sample Output
6 5
看少一句话都可能理解不了题意,阅读能力啊。
算法就是使用递归回溯剪枝法,这里就考个人的剪枝功力了,剪枝好的可以0MS过,不好的可能慢很多。
下面我写了个类包起来,最终运行是0MS AC的。
#include <iostream>
#include <string.h>
#include <algorithm>
using namespace std;
bool stiCmp(const int a, const int b)
{
return a > b;
}
class recombineSticks
{
int sticks[64], n, len, num;//这里如果使用static就会出错信息:无法解析外部符号
bool used[64];//这里如果使用static就会出错信息:无法解析外部符号
public:
bool backTrack(int left, int cur = 1, int lv=0)
{
if (!left)
{
if (lv + 2 == num) return true;
for (cur = 1; used[cur]; cur++);//重新找到新的没用过木棒进行递归
used[cur] = true;
if (backTrack(len - sticks[cur], cur+1, lv+1)) return true;
used[cur] = false;
}
else
{
if (n <= cur) return false;
for (int i = cur; i < n; i++)
{
if ( used[i] || !used[i-1] && sticks[i] == sticks[i-1] ||
sticks[i]>left) continue;//错误不是!used[i]
used[i] = true;
if (backTrack(left - sticks[i], i+1, lv)) return true;
used[i] = false;
}
}
return false;
}
void run()
{
while (cin>>n && 0 != n)
{
//fill(used, used+64, false);
memset(used, 0, sizeof(used));
int sum = 0;
for (int i = 0; i < n; i++)
{
cin>>sticks[i];
sum += sticks[i];
}
sort(sticks, sticks + n, stiCmp);
bool ok = false;
used[0] = true;
for (len = sticks[0]; len <= (sum>>1); len++)
{
if (sum % len == 0)//可以凑成整条的木棒
{
num = sum / len;
if (backTrack(len - sticks[0]))
{
ok = true;
cout<<len<<endl;
break;
}
}
}
if (!ok) cout<<sum<<endl;
}
}
};
int main()
{
recombineSticks sti;
sti.run();
return 0;
}
个人觉得还是下面这个博客写的代码最清晰了,这里参照了他的代码
http://ren.iteye.com/blog/344095