POJ1011-Sticks DFS+剪枝

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

题目大意是有一些等长的木棍,现将他们剪成小木棍,剪短后的小木棍最多有六十四根。题目输入数据给定剪短后的小木棍的长度,求将其恢复成原来的木棍的最短长度。

本题剪枝要求较高:

剪枝(1):由于小木棍是由原来木棍剪短后得到的,那么原来木棍的长度最短的也大于等于最长的小木棍,但不会超过所有小木棍长度之和;

剪枝(2):注意到原木棍长度是等长的,则将所有小木的长度加起来后,若不能按当前要搜索的值平均分配,那么剪掉。

qsort(a,n,sizeof(int),cmp);  //将所有小木棍按从大到小的顺序排序
for (i=a[0];i<=sum;i++)      //我们只需枚举 最长的小木棍长度 到 所有小木棍长度之和。
{
    if (sum%i==0&&dfs(0,0,0,i)) //如果所有小木棍长度之和不能按当前要搜索的值平均分配,那么剪掉不搜索。因为原木棍长度等长。
    {
       break;
    }
}

剪枝(3):由于所有棒子已降序排序,在DFS时,若某根棒子不合适,则跳过其后面所有与它等长的棒子;

剪枝(4):最重要的剪枝,开始没加这个剪枝,我TL,加了这个剪枝后,POJ上16ms。对于每次重新构造原始木棍长度时,若从第一根木棍开始搜索,无法组合成功,则不需要继续往后搜索,因为当前木棍若不能和其他木棍组合成原始木棍则就需要被舍弃,但是组成所有的原始木棍不能舍弃任何一根小木棍!

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define MAX 70
#define INF 0xfffffff
int a[MAX],flag[MAX];
int n;
int cmp(const void *a,const void *b)
{
    return *(int *)b-*(int *)a;
}
int dfs(int tot,int s,int sum,int max)  //四个参数分别为tot-已经使用的小木棍数,s-上次搜索到第几根小木棍
//sum-当前已经组合的小木棍长度,max-原始木棍的长度。
{
    if (tot==n) //这是阀值,即所有木棍被用完,搜索结束
    {
       return 1;     
    }
    int i,sample=-1;;
    for (i=s;i<n;i++)
    {
        if (flag[i]||sample==a[i])   //如果当前木棍被用过了,
	//或者与当前木棍等长的小木棍在此次组合成原始木棍中不能用时,当前木棍也不用检索,跳过。剪枝(3);
           continue;
        flag[i]=1;
        if (flag[i]&&sum+a[i]<max)
        {
           if (dfs(tot+1,i,sum+a[i],max))              
           {
               return 1;                                    
           }
           else
           {
               sample=a[i];   //这根木棍在此次组合中不能使用,则记录,下次遇到等长跳过
           }
        }
        else if (sum+a[i]==max)  // 若组合成一根原始木棍
        {
             if (dfs(tot+1,0,0,max))  //则从从第一根木棍开始搜索,并且将记录的小木棍组合的长度置零重新开始组合另一根原始木棍。
                return 1;
             else
             {
                sample=a[i];  
             }
        }
        flag[i]=0;
        if (sum==0)  //剪枝(4)若上面的木棍组合成功便会return,否则代表无法组合。
           break;
    }
    return 0;    
}
int main()
{
    while (scanf("%d",&n)!=EOF)
    {
          if (n==0)
             break;
          int i,j,sum=0,max=-INF;
          for (i=0;i<n;i++)
          {
              scanf("%d",&a[i]);
              flag[i]=0;
              sum+=a[i];
          }      
          qsort(a,n,sizeof(int),cmp);
          for (i=a[0];i<=sum;i++)
          {
              if (sum%i==0&&dfs(0,0,0,i))
              {
                 break;
              }
          }
          printf("%d\n",i);
    }
    return 0;    
}




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章