欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

POJ1011-Sticks 搜索

程序员文章站 2024-03-23 21:45:04
...

Sticks
Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 151709   Accepted: 36124

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.

链接

一、题意

        现在有n根长度不一的小木棒,要求将其拼凑成长度相等的木棒若干。要求输出长度最短的可能。

二、思路

        主要思路是搜索,但要加上剪枝才能不超时。搜索时传入剩余的木棒数量,当前已经拼凑的长度。按照我的搜索策略,主要有一下几种剪枝:

                1.设拼凑完成后长度为len,则len必定能整除原来木棒的长度和sum。

                2.对于新的一次拼凑过程,即当前已经拼凑的长度为0,则要求此次拼凑必须成功。因为若此次拼凑不能成功,意味着存在一根木棒,在以后的搜索过程中都不会完成拼凑。

                3.对源木棒进行降序排列,先拼凑长木棒。

                4.搜索过程中,对于长度相等的木棒应该避免重复搜索。

        即使这样,Discuss中的数据还是要7秒左右。

三、代码

#include <iostream>
#include <sstream>
#include <iomanip>
#include <string>
#include <numeric>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#include <utility>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>

using namespace std;
typedef long long ll;
const int MAXN = 1000;
const int MOD7 = 1000000007;
const int MOD9 = 1000000009;
const int INF = 2000000000;//0x7fffffff
const double EPS = 1e-9;
const double PI = 3.14159265358979;
const int dir_4r[] = { -1, 1, 0, 0 };
const int dir_4c[] = { 0, 0, -1, 1 };
const int dir_8r[] = { -1, -1, -1, 0, 0, 1, 1, 1 };
const int dir_8c[] = { -1, 0, 1, -1, 1, -1, 0, 1 };

int n;
int val[MAXN];
bool visited[MAXN];

bool myCom(int a, int b) {
	return a > b;
}

bool dfs(int left, int cur, int len, int beg) {
	if (left == 0 && cur == 0)
		return true;
	else if (cur == 0) {
		//如果是拼接一根新的木棒,则这根木棒必须完成拼接
		int index = 0;
		while (visited[index])
			index++;
		visited[index] = true;
		if (dfs(left - 1, val[index] % len, len, index + 1))
			return true;
		visited[index] = false;
		return false;
	}

	for (int i = beg; i < n; ++i)
		if (!visited[i])
			if (cur + val[i] <= len) {
				visited[i] = true;
				if (dfs(left - 1, (cur + val[i]) % len, len, i + 1))
					return true;
				visited[i] = false;
				//减少重复搜索
				while (i < n && val[i + 1] == val[i])
					i++;
			}

	return false;
}

int main() {
	while (scanf("%d", &n) && n) {
		int sum = 0;
		for (int i = 0; i < n; ++i) {
			scanf("%d", val + i);
			sum += val[i];
		}
		sort(val, val + n, myCom);

		int len;
		for (len = val[0]; len < sum; ++len)
			if (sum % len == 0) {
				memset(visited, false, sizeof(visited));
				if (dfs(n, 0, len, 0))
					break;
			}
		printf("%d\n", len);
	}

	//system("pause");
	return 0;
}