您的位置:首页 > 其它

POJ 1011 Sticks CODE[VS] 3498 小木棍(DFS+剪枝优化)

2016-09-27 21:14 423 查看
剪枝神题

CODE[VS]3498只不过是一组数据最后没有0而已 =_=

木棒

Time Limit: 1000MS Memory Limit: 10000K

Total Submissions: 139356 Accepted: 32861

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

非常不错的一道剪枝优化练习题

解法:DFS+剪枝

剪枝如下:

1.搜索下一根长棍子的时候,找到第一个还没有使用的小棍子开始 由于排序过,找到的第一根肯定最长,也肯定要使用,所以从下一根开始搜索

2.前后两根长度相等时,如果前面那根没被使用,也就是由前面那根开始搜索不到正确结果,那么再从这根开始也肯定搜索不出正确结果

3.要拼成一根大棍子还需要的长度L>=当前小棍子长度,才能选用

4.本次的小棍长度刚好填满剩下长度,但是后面的搜索失败,则应该返回上一层

代码如下:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int size=10010;
int num[size],n,sum;
bool used[size];
int cmp(int x,int y) {return x > y;}
//tot 总数,unused没用过得  rml 当前与验证的答案差多少 len 要验证的答案
bool dfs(int tot,int unused,int rml,int len)
{
if(unused == 0 && rml == 0)  return true;
//如果剩余木棍为0,剩余长度为0,拼接完成
if(rml == 0) rml = len;
//当前拼接木棍剩余长度为0时尝试新的一个原始长度
for(int i = 1;i <= tot; i ++)//从第一个开始找到最好一个
{
if(used[i] == true) continue;
//用过的不优先考虑
if(num[i] > rml) continue;
//如果当前的木棍比当前差的要少  跳走
used[i] = true;
if(dfs(tot,unused-1,rml-num[i],len)==true) return true;
//如果答案符合要求
used[i] = false;
//寻找下一个木棍
if(num[i] == rml || rml == len) break;
//如果某个木棍一上来就等于答案差或最好答案差还是等于原长说明没有木棍跟它匹配
}
return false;
}

void init()
{
memset(num,0,sizeof(num));
memset(used,0,sizeof(used));
sum = 0;
}
int main()
{
//  while (scanf("%d",&n))
//  {
scanf("%d",&n);
if(n == 0) return 0;
init();
for(int i = 1;i <= n;i ++)
{
scanf("%d",&num[i]);
sum += num[i];
}
sort(num + 1,num + n + 1,cmp);
for(int i = num[1];i <= sum;i ++)
{
if(sum % i == 0)
if(dfs(n,n,0,i) == true)
{
printf("%d\n",i);
break;
}
}
//  }
return 0;
}


加了剪枝就有些迷了呀QAQ

自己还得慢慢参透这份代码

搜素还得慢慢补 加油吧QAQ
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: