1. 程式人生 > >hdu1455Sticks深搜+剪枝

hdu1455Sticks深搜+剪枝

題意:

有多個相同長度的木棍,將它們隨機切成n個小木棍,現在要把它們還原,問原先的木棍長度最短可以是多少 小木棍的長度最大為50,n最大為64

題解:

把給定的長度木棍排序從小到大

列舉長度,從最小值不斷+1,先判斷是否能被其總長度整除,能整除進行深搜,不能則繼續

深搜過程:

深搜引數:標記陣列,湊木棍當前長度,目標長度,當前位置,木棍當前用量;

如果len+stick[i]<目標長度,繼續深搜;

如果等於目標長度,繼續深搜,標記當前位置為0;

p為本次深搜所用的不合要求的長度,剪枝

flag[i]標記已用木棍;

#include <cstdio>
#include <cstdlib>
#include <cstring>
#define MAX 70
int n;
int sticks[MAX];
int sum_len;

int cmp(const void *a,const void *b)
{
    return *((int *)b)-*((int *)a);
}
bool dfs(bool *flag,int len,int a_len,int s,int num)        //flag標記,len當前長度,a_len目標單根長度,s當前搜尋位置,num當前總用量
{
    //標記,當前長度,目標長度,搜尋位置,當前用量;
    if(num==n)
        return true;//結束;
    int p=-1;                 //高效剪枝,不遞迴相同且不可用的枝條
    for(int i=s; i<n; i++)
    {
        if(flag[i] || p==sticks[i]) continue;
        flag[i]=1;//標記已經用過;
        if(len+sticks[i]<a_len)
        {
            //小於目標長度,繼續深搜;
            if(dfs(flag,len+sticks[i],a_len,i,num+1)) return true;//注意不成立還需要繼續下一個小木段
            else
                p=sticks[i];//代表這種長度不行...剪枝,只在本次深搜中發揮作用;
        }
        else if(len+sticks[i]==a_len)
        {
            //這個已經滿足;
            //繼續深搜下一個長度,從0開始;
            if(dfs(flag,0,a_len,0,num+1))return true;//一個木棍滿足了條件,0位置?;
            else
                p=sticks[i];//剪枝...這一個行,但是下一個又不行,也不滿足;
        }
        flag[i]=0;//回溯;
        if(len==0)//剪枝,當沒有能夠組合出木棍,說明木棍可能已經用完了。
            break;
    }
    return false;
}
int main()
{
    bool flag[MAX];//定義flag陣列;
    while(~scanf("%d",&n) && n)
    {
        sum_len=0;
        for(int i=0; i<n; i++)
        {
            scanf("%d",&sticks[i]);
            sum_len+=sticks[i];
        }//得到所有木棒的總長度;
        qsort(sticks,n,sizeof(int),cmp);//按照給定木棒長度排序;
        int MinLen=sum_len;
        for(int i=sticks[0]; i<=sum_len; i++) //從最短的木棒長度列舉到所有長度之和i++;
        {
            if(sum_len%i==0)
            {
                memset(flag,0,sizeof(flag));			//
                if(dfs(flag,0,i,0,0)) //長度為i
                {
                    MinLen=i;
                    break;
                }
            }
        }
        printf("%d\n",MinLen);
    }
}