poj 1011 Sticks (DFS+剪枝)

原创 2015年07月08日 12:52:52

Sticks
Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 127771   Accepted: 29926

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


题目链接:http://poj.org/problem?id=1011


题目大意:有n根木棍,用它们拼成一些等长的木棍,求拼出的木棍的最短长度。


解题思路:这题的时间限制特别严格。DFS+剪枝,剪枝较多。首先由多到少枚举木棍数目num,即从n到1,要满足木棍总长度是num的倍数,且拼出的长度要不小于最长的木棍长度,否则无法拼,搜索到答案后退出循环,保证求出的木棍长最短。

剪枝:1.木棍由长到短排序。

   2.访问过的木棍或者加上当前木棍长度后超过了目标长度,则跳过本次循环。

   3.若当前木棍和上一根木棍长度相同并且上一根木棍没用到,则跳过本次循环。

   4.dfs中标记开始木棍下标。


代码如下:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int a[66],vis[66];
int n,num,m;
bool p;
int cmp(int a,int b)
{
	return a>b;
}
void dfs(int st,int cur,int cnt)
{
	if(p||cnt==num)
	{
		p=true;
		return ;
	}
	for(int i=st;i<n;i++)
	{
		if(vis[i]||cur+a[i]>m)    //访问过的木棍或者加上当前木棍长度后超过了目标长度,则跳过本次循环
			continue;
		if(i-1&&!vis[i-1]&&a[i]==a[i-1])    //若当前木棍和上一根木棍长度相同并且上一根木棍没用到,则跳过本次循环。
			continue;
		if(a[i]+cur==m)
		{
			vis[i]=1;
			dfs(0,0,cnt+1);
			vis[i]=0;
			return;				//循环里后面的值都在dfs中求过了,这里直接返回上一层
		}
		if(a[i]+cur<m)
		{
			vis[i]=1;
			dfs(i+1,a[i]+cur,cnt);
			vis[i]=0;
			if(cur==0)           //cur为0时,直接返回上一层
				return ;
		}
	}
}
int main()
{
	while(scanf("%d",&n)!=EOF&&n)
	{
		int sum=0;
		p=false;
		memset(vis,0,sizeof(vis));
		for(int i=0;i<n;i++)
		{
			scanf("%d",&a[i]);
			sum+=a[i];
		}
		sort(a,a+n,cmp);
		for(num=n;num>=1;num--)
		{
			if(sum%num||a[0]>sum/num)
				continue;
			m=sum/num;
			dfs(0,0,0);
			if(p)
				break;
		}
		printf("%d\n",m);
	}
	return 0;
}




版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

poj 1011 sticks (dfs+剪枝)

一道很经典的搜索题。还要一定的剪枝。题意:给出了由若干根等长的棒子剪成的n根短棒子的长度,求出长棒子的最小长度。思路:首先把所有的小棒子的长度加起来得到sum,然后通过排序找出所有长度里面最长(sti...

hdu 1455/poj 1011 Sticks(DFS剪枝神题)

Sticks Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total S...
  • acm_cxq
  • acm_cxq
  • 2016年08月08日 21:05
  • 194

poj1011 -- Sticks (DFS+剪枝)

Sticks Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 143809   Accepted: 33965 ...
  • BestFSQ
  • BestFSQ
  • 2017年04月05日 23:43
  • 119

POJ 1011 Sticks(DFS+剪枝)详细注释

题目链接:http://poj.org/problem?id=1011Sticks Time Limit: 1000MSMemory Limit: 10000K Total Submissions...

hdoj1455 poj1011 nyoj293 Sticks【DFS+剪枝】

Sticks Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 128649   Accepted: 30149 ...

POJ 1011 Sticks DFS 剪枝

Sticks Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 113953   Accep...
  • kdwycz
  • kdwycz
  • 2014年01月08日 23:31
  • 628

POJ 1011 Sticks dfs+剪枝

Sticks Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 129130   Accepted: 30264 ...

POJ1011-Sticks DFS+剪枝

题目链接:http://poj.org/problem?id=1011 题目大意是有一些等长的木棍,现将他们剪成小木棍,剪短后的小木棍最多有六十四根。题目输入数据给定剪短后的小木棍的长度,求将其恢复成...

POJ 1011 Sticks(DFS + 剪枝)

Sticks Description George took sticks of the same length and cut them randomly until all parts b...

poj1011-Sticks dfs各种剪枝

Sticks Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 133058   Accepted: 31236 ...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:poj 1011 Sticks (DFS+剪枝)
举报原因:
原因补充:

(最多只允许输入30个字)