• 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;
    }
    
  • 相关阅读:
    简单协议解析
    三刺激值
    74hc595
    色彩理论
    灰度值和强度值概念
    RGB 常用颜色对照表
    IAR注释的快捷键
    visual studio 2015 2017 key vs2015 vs2017密钥
    如何在cmd命令行中查看、修改、删除与添加环境变量
    win cmd 设置代理
  • 原文地址:https://www.cnblogs.com/1625--H/p/9488500.html
Copyright © 2020-2023  润新知