poj 1011 Sticks DFS 剪枝

来源:互联网 发布:linux cat和more 编辑:程序博客网 时间:2024/06/07 03:21

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

95 2 1 5 2 1 5 2 141 2 3 40

Sample Output

6

5

剪枝1:棍子从大到小进行排序,配合剪枝2使用

剪枝2:记录每次遍历到第几个棍子了,如果是重新找新的,那么从0开始遍历,否则就是从记录的位置开始遍历

剪枝3:重新开始找新的,不用for,因为我们必须从未使用的第一个开始找起,没必要for重复计算后面的

剪枝4:枚举棍子的长度,从最大值开始枚举,因为最小也是小棍子最长的长度

剪枝5:重复的跳过去,利用while循环,防止重复计算

#include <iostream>#include <algorithm>#include<stdio.h>#include<string.h>using namespace std;int sticks[65];int used[65];int n,len;bool dfs(int i,int l,int t)//i为当前试取的棍子序号,l为要拼成一根完整的棍子还需要的长度,t初值为所有棍子总长度{    if(l==0)    {        t-=len;        if(t==0)return true;        for(i=0;used[i];++i);                   used[i]=1;                               if(dfs(i+1,len-sticks[i],t))return true;        used[i]=0;        t+=len;    }    else    {        for(int j=i;j<n;++j)        {            if(j>0&&(sticks[j]==sticks[j-1]&&!used[j-1]))                  continue;                                                          if(!used[j]&&l>=sticks[j])               {                l-=sticks[j];                used[j]=1;                if(dfs(j,l,t))return true;                l+=sticks[j];                used[j]=0;            }        }    }    return false;}bool cmp(const int a, const int b){    return a>b;}int main(){    while(cin>>n&&n)    {        int sum=0;        for(int i=0;i<n;++i)        {            cin>>sticks[i];            sum+=sticks[i];        }        memset(used,0,sizeof(used));        sort(sticks,sticks+n,cmp);           bool flag=false;        for(len=sticks[0];len<=sum;++len)           {            if(sum%len==0)            {                if(dfs(0,len,sum))                {                    flag=true;                    cout<<len<<endl;                    break;                }            }        }        if(!flag)            cout<<sum<<endl;    }    return 0;}

原创粉丝点击