sticks hdu 1455 dfs+减枝

题意,给出被割断的n个树枝的长度;

求出其最小原长.

input

9

5 2 1 5 2 1 5 2 1

6

4

1 2 3 4

5

0

经典的一道深授,要经过多次减枝:

//第一次,从大到小判断短棒;即如(a,b,c)其中c=a+b;则总先判断c;

//第二次,y记录判断到第几根木棒,下一次选取木棒则从第几根开始.

 //第三次,若判断第i根木棒失败,则不必判断与其相同长度的木棒.

//第四次,选取好原木棒后,若第一次选取木棒就失败,则直接退出.

 

 

同时再熟悉一下深搜的过程,深搜主要用在,搜索过程中需要不断的尝试,了解尝试的条件与尝试失败的条件;

一般格式:

在适当位置加上搜索成功条件

return true;

if(符合尝试条件)

标记vis【】=true

dfs();

(失败)尝试失败后条件与操作;

vis【】=false;

代码:

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=100;
int vis[N];
int a[N];
int sum,n;
int cmp(int x,int y)
{
    return x>y;
}
int dfs(int y,int mix,int p,int k)      //第二次,y记录判断到第几根木棒,下一次选取木棒则从第几根开始.
{
    int pp,i;
    if(k*mix==sum) return 1;        //结束条件
    for(i=y+1;i<=n;i++)
      {
        if(!vis[i]&&p-a[i]>=0)
        {
            vis[i]=1;
            if(p-a[i]==0)
            {
                pp=dfs(0,mix,mix,k+1);
            }
            else if(p-a[i]>0)
            {
                pp=dfs(i,mix,p-a[i],k);
            }
            vis[i]=0;   //失败
            if (y==0) return pp;        //第四次,选取好原木棒后,若第一次选取木棒就失败,则直接退出.
            else if (pp) return pp;
            while(a[i]==a[i+1])i++;     //第三次,若判断第i根木棒失败,则不必判断与其相同长度的木棒.
        }
      }
      return 0;
}
int main()
{
    int i,mix;
    while(cin>>n,n)
    {
        sum=0;
        memset(vis,0,sizeof(vis));
        memset(a,0,sizeof(a));

        for(i=1;i<=n;i++)
        {
            cin>>a[i];
            sum+=a[i];
        }

        sort(a+1,a+n+1,cmp);            //第一次,从大到小判断短棒;即如(a,b,c)其中c=a+b;则总先判断c;
        int ans=sum;
        for(i=a[1];i<=sum/2;i++)
        {
            mix=i;
            if(sum%mix==0&&dfs(0,mix,mix,0))
            {
                ans=mix;
                break;
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}

 

posted @ 2012-12-03 16:25  amourjun  阅读(155)  评论(0编辑  收藏  举报