zoukankan      html  css  js  c++  java
  • POJ-1011(sticks,深搜)

    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
    

    分析:

    • 先存大的棍子,对于每一次搜索,关心的状态有三个:现在拼的棍子是第几个,已经拼了多少了,上次拼的那根是序列中的第几根
    • 如果拼当前棍子的时候,拼了一个长度为a的棍子,发现失败了,那么之后就不用再尝试长度为a的棍子了
    • 如果现在要拼的棍子长度为0,然后发现有一个棍子试图去拼然后失败了,那么这条路子就是错的,因为最终肯定不会全部拼完整,
    • 同理,如果刚好拼好一根棍子,发现接下来再拼失败了,那么接下来也没办法成功拼完整的。
    int a[100],v[100],n,cnt,len;
    
    bool cmp(int a,int b)
    {
    	return a>b;
    }
    bool dfs(int stick,int cab,int last)
    {
    	if(stick == cnt+1)
    		return true;
    	if(cab == len)
    		return dfs(stick+1,0,1);//这里第一次忘记return了,好坑
    	int fail = 0;
    	for(int i=last;i<=n;i++)
    	{
    		if(!v[i]&&cab+a[i]<=len&&fail!=a[i])
    		{
    			v[i] = 1;		if(dfs(stick,cab+a[i],i+1))
    				return true;
    			fail = a[i];
    			v[i] = 0;
    		    //如上述最后两条所说
    		    if(cab==0||cab+a[i]==len)
    				return false;
    		}
    	}
    	return false;
    }
    int main() 
    {
        while(cin>>n,n)
        {
        	int sum = 0,val = 0;
        	for(int i=1;i<=n;i++)
        	{
        		scanf("%d",&a[i]);
        		sum+=a[i];
        		val = max(val,a[i]);
        	}
        	sort(a+1,a+1+n,cmp);
        	for(len = val;len<=sum;len++)
        	{
        		if(sum%len)continue;
        		cnt = sum/len;
        		//cout<<cnt<<endl;
        		memset(v,0,sizeof v);
        		if(dfs(1,0,1))break;
        	}
        	cout<<len<<endl;
        }
        return 0;
    }
    
  • 相关阅读:
    C#-MessageBox全部函数重载形式及举例
    在软件开发中应用80:20原则
    C# 程序员最常犯的 10 个错误
    关于vs2013调试的偶然错误发现与总结(vs2013的承载进程)---ShinePans
    C#好书盘点
    C#中 父类与子类相互强制转换之实验
    如何用C#语言构造蜘蛛程序
    C#创建word,操作、读写
    Linux less/more命令详解
    Linux 环境变量详解
  • 原文地址:https://www.cnblogs.com/1625--H/p/9488500.html
Copyright © 2011-2022 走看看