1poj1011(dfs剪枝)

http://poj.org/problem?id=1011

Sticks
Time Limit: 1000MSMemory Limit: 10000K
Total Submissions: 99830Accepted: 22703

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

Source

题意:有中文版我rp不好老是看到英文的。。
这题经提醒获知和poj2362几乎一样就把那题的代码改了改。
Accepted164K16MS

//代码1:RE 

#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define maxn  100000000
__int64 a[maxn];
int main()
{
__int64 n;
while(scanf("%I64d",&n)!=EOF)
{
if(n==0)
break;
int i;
__int64 sum=0;
for(i=0;i<n;i++)
{
scanf("%d",&a[i]);
sum+=a[i];
}
sort(a,a+n);
for(i=n;i>=1;i--)
{
if(sum%i==0&&sum/i>a[n-1])
break;
}
printf("%I64d\n",sum/i);
}
return 0; 
}

 

 

 

代码2:ac
#include<iostream>
#include<algorithm>
using namespace std;
#define MAX 70
int n; //小棒总数
int average; //小棒的平均长度
int parts;//当前组合的原棒数
int  maxn;//最长小棒的长度
int sum;
int a[MAX];//存储小棒相关信息
bool used[MAX]; //标记小棒是否使用
bool pt(int a,int b)//从大到小排序
{
return a>b;
}
//cur_long: 当前长度
//tot: 找到几段木棒了
//I:为数组下标
bool dfs(int cur_long,int tot,int I)
{
int i;
if(tot==parts)//剪枝3,已经有3条边满足条件最后一条边肯定满足因为最后一条边=sum-3*averge
return true;
for(i=I;i<n;i++)
{
if(i&&!used[i-1]&&a[i-1]==a[i])//剪枝4同样长度的木棍不行那么下一个与它一样长的木棒肯定不行
continue;// //当两根木棍相等时,如果前一根木棍没有选取,则后面一条木棍也不可能满足要求
if(!used[i])
{
if(cur_long+a[i]<average)
{
used[i]=true;
if(dfs(cur_long+a[i],tot,i+1))//还没构造好,继续选木棍
return true;
used[i]=false;
}
else if(cur_long+a[i]==average)
{
used[i]=true;
if(dfs(0,tot+1,0))//从0开始构造第tot+1条边
return true;
used[i]=false;
}
if(cur_long==0)//剪枝5,构建新棒时,对于新棒的第一根棒子,在搜索完所有棒子后都无法组合
break;//则说明该棒子无法在当前组合方式下组合不用往下搜索(往下搜索会令该棒子被舍弃)直接返回上一层
}
}
return false;
}
int main()
{
int i;
while(scanf("%d",&n)!=EOF)
{

sum=0;
maxn=0;
for(i=0;i<n;i++)
{
scanf("%d",&a[i]);
sum+=a[i];
//used[i]=false;//初始清全部为false
}
sort(a,a+n,pt);//从大到小排序
maxn=a[0];
for(i=maxn;i<=sum;i++)
{
if(sum%i==0)
{
memset(used,0,sizeof(used));
average=i;
parts=sum/i;
if(dfs(0,0,0))
{
printf("%d\n",i);
break;
}
}
}
}
return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值