【深搜加剪枝】【HDU1455】【Sticks】

题目大意:有一堆木棍 由几个相同长的木棍截出来的,求那几个相同长的木棍最短能有多短?


深搜+剪枝 具体看代码

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <ctime>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <string>
#define oo 0x13131313
using namespace std;
int N,M;
int A[100],Max=-1,Sum,NN;
int visit[100];
bool cmp(int a,int b)
{
    return a>b;
}

void input()
{
    memset(visit,0,sizeof(visit));
    Max=-1;Sum=0;
    for(int i=1;i<=N;i++)
    {
        scanf("%d",&A[i]);
        if(A[i]>Max) Max=A[i];
        Sum+=A[i];
    }
}
int dfs(int now,int nown,int pos)
{
    int ok=0;
    if(nown==NN) return 1;
        for(int i=pos+1;i<=N;i++)
        {
            if(visit[i]==0)
            {
                if(now+A[i]<=M)
               {
                visit[i]=1;
                if(now+A[i]==M) ok=dfs(0,nown+1,0);
                else  ok=dfs(now+A[i],nown,i); //剪枝1  次要剪枝
                visit[i]=0;
                if(ok) return 1;
                if(now==0) return 0;        //剪枝2  必须剪枝 now==0 表示这是一个新的一根但i却依旧不能加进去
                                            //       在新的一根中都不能满足,说明未来所有的木棍中都没有他的容身之所,直接return 0;本题精华所在
                while(A[i]==A[i+1]) i++;    //剪枝3  次要剪枝 如果这个不满足的话,与他相同的也不可能满足这根
               }
            }
        }
    return 0;
}
void solve()
{
    sort(A+1,A+N+1,cmp);
    for(int i=Max;i<=Sum;i++)
    {
       if(Sum%i==0)
       {
           memset(visit,0,sizeof(visit));
           M=i;
           NN=Sum/i;
           if(dfs(0,0,0)) {
                            printf("%d
",M);
                            break;
                        }
       }
    }
}
void init()
{
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
}
int main()
{
   // init();
	while(cin>>N&&N!=0)
    {
        input();
        solve();
    }
}


原文地址:https://www.cnblogs.com/zy691357966/p/5480401.html