您的位置:首页 > 其它

Sticks

2016-09-04 15:38 323 查看
链接:http://acm.hust.edu.cn/vjudge/problem/14913/origin

题目: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.

题意:有一堆长度不同的木棍,用他们去拼成一些长度相等的木棍,问,长度相等的木棍最短为多少。

分析:这是一道稍显复杂的搜索题,答题思路是从0开始枚举长度,挨个去寻找看是否成功,需要找到一些规则来优化,否则会超时。第一个优化:枚举范围,最短的长度一定大于等于单个最长的小木棍,而且保证能被总长度除尽,最长为总长度(可以简化成总长度的一半,一旦超过了,就只能是总长度了),第二个优化:把小木棍从大的开始选择,这样对于目标长度,比如3,会优先选择木棍少的情况,比如3,12,111的情况要优先选择3,因为木棍越短,数量越多拼凑起来越灵活,对复杂的情况有帮助。第三个优化,同一个长度的木条,在同一个阶段,只尝试一次(非常的重要),比如在选择第二条木棒3+2(第一个2)+。。。失败了,就不要再尝试3+2(第二个,第三个。。)了,因为不会成功的。题目不是很难,不过剪枝的比较多,比较考验细心程度。wrong出翔。

题解:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <string>
#include <cstring>
#include <functional>
#include <cmath>
#include <cctype>
#include <cfloat>
#include <climits>
#include <complex>
#include <deque>
#include <list>
#include <set>
#include <utility>
#define rt return
#define fr freopen("in.txt","r",stdin)
#define fw freopen("out.txt","w",stdout)
#define ll long long
#define ull unsigned long long
#define detie ios_base::sync_with_stdio(false);cin.tie(false);cout.tie(false)
#define pii pair<int,int>
#define lowbit(x) x&(-x)
using namespace std;
#define maxi 0x3f3f3f3f
#define MAX 300020

int s[MAX];
bool v[MAX];
int sum;
int n;

bool dfs(int pos, int res, int len) {
if (pos == 0 && res == 0)
rt true;
if (res == 0)
res = len;
for (int i = n - 1; i >= 0; i--){
if (v[i] || s[i] > res)
continue;
v[i] = true;
if (dfs(pos - 1, res - s[i], len))
rt true;
v[i] = false;
if (res == s[i] || res == len)//重要的剪枝,长度相同不会重复尝试。
rt false;
}
rt false;
}

int main(){
//fr;
detie;
while (cin >> n&&n){
sum = 0;
for (int i = 0; i < n; i++){
cin >> s[i];
sum += s[i];
}
sort(s, s + n);
int i;
for (i = s[n - 1]; i <= sum/2;i++){
if (sum%i)
continue;
memset(v, 0, sizeof v);
if (dfs(n,i,i)){
printf("%d\n", i);
break;
}
}
if (i > sum / 2)
printf("%d\n", sum);
}
rt 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  dfs 剪枝