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;    
}




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