POJ 1011 木棒问题

来源:互联网 发布:js数据类型转换函数 编辑:程序博客网 时间:2024/05/01 22:11
•问题描述:   
         乔治拿来一组等长的棍子,将它们随机地裁断(截断后的小段称为木棒),使得每一节木棒的长度都不超过50个长度单位。然后他又想把这些木棒恢复到为裁截前的状态,但忘记了棍子的初始长度。请你设计一个程序,帮助乔治计算棍子的可能最小长度。每一节木棒的长度都用大于零的整数表示
 
       
输入数据
由多个案例组成,每个案例包括两行。第一行是一个不超过64的整数,表示裁截之后共有多少节木棒。第二行是经过裁截后,所得到的各节木棒的长度。在最后一个案例之后,是零。
输出要求
为每个案例,分别输出木棒的可能最小长度,每个案例占一行。
输入样例
9
5 2 1 5 2 1 5 2 1
4
1 2 3 4
0
输出样例
6
5

 

剪枝1:

每次开始拼第i根棍子的时候,必定选剩下的木棒里最长的一根,作为该棍子的第一根木棒。对此决不后悔。
就算由于以后的拼接失败,需要重新调整第i根棍子的拚法,也不会考虑替换第i根棍子中的第一根木棒(换了也没用)。
因为假设替换后能全部拼成功,那么这被换下来的第一根木棒,必然会出现在以后拼好的某根棍子k中。那么我们原先拼第i根棍子时, 就可以用和棍子k同样的构成法来拼,照这种构成法拼好第i根棍子,继续下去最终也应该能够全部拼成功

剪枝2:

不要希望通过仅仅替换已拼好棍子的最后一根木棒就能够改变失败的局面。

剪枝3:

如果某次拼接选择长度为L1的木棒,导致最终失败,则在同一位置尝试下一根木棒时,要跳过所有长度为L1的木棒。

剪枝4:

拼每一根棍子的时候,确保已经拼好的部分,长度是从长到短排列的
 
代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;

int len[100];
int Length,n;
bool use[100];

bool cmp(int a,int b)
{ return a>b; }

bool dfs(int Notused,int NLeft,int preno/*剪枝4*/)
{
    if(Notused==0&&NLeft==0)
        return true;
    if(NLeft==0)
    {
  NLeft=Length;
  preno=0;
 }
 if(preno!=0)
     preno+=1;
    int i;
    for(i=preno;i<n;i++)
    {
        if(i>0&&use[i-1]==false&&len[i]==len[i-1])
            continue;//剪枝3
        if(!use[i]&&len[i]<=NLeft)
        {
   use[i]=true;
            if(dfs(Notused-1,NLeft-len[i],i))
                return true;
            else
            {
                use[i]=false;
                if(NLeft==len[i]||Length==NLeft)
                    return false;//剪枝2 剪枝1
            }
        }
    }
    return false;
}

int main()
{
    //int n;
    int i,sum;
    while(scanf("%d",&n)&&n)
    {
        memset(len,0,sizeof(len));
        for(i=sum=0;i<n;i++)
        {
            scanf("%d",&len[i]);
            sum+=len[i];
        }
        sort(len,len+n,cmp);
        for(i=len[0];i<=sum;i++)
        {
            if(sum%i!=0) continue;
   memset(use,false,sizeof(use));
            //printf("%d\n",i);
            Length=i;
            if(dfs(n,i,0))
            {
                printf("%d\n",i);
                break;
            }
        }
    }
    return 0;
}

原创粉丝点击