poj - 1011 Sticks

题目也挺难懂的,要仔细审题,其实就是一句话搞定的意思:把一组数组合成所有数值相等的一组新的数列。

看她题目说了一大堆:

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



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值