深搜+剪枝(小木棍)

优化1.将每根木棍从长到短排序,先选长的后选短的,这样会使选择的情况尽可能少

优化2.拼好的木棍內部编号由大到小,即当一根木棍没有拼接好时,所寻找可以拼接上的下一根木            棒一定是从上一根所用木棒之后开始寻找

优化3.当开始寻找第一根木棒失败时,那么这种情况就不可能找到解

优化4.当将一根木棒拼接上去之后继续寻找时失败后,跳过与该木棒长度相同的所有木棒

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;

const int N=65;
int a[N],b[N];
int n,m,sum,length,x,k;

bool dfs(int now,int cur,int strat)//now现在拼好了多少根,cur目前拼的这根拼了多长,strat从该下标开始查找
{
    if(now*length==sum)//如果现在现在拼的数量与长度乘起来等于总长度,说明拼接成功
        return true;
    if(cur==length)//目前这跟的长度等于length,就开始寻找下一根,strat从0开始;
        return dfs(now+1,0,0);
    for(int i=strat;i<k;i++)
    {
        if(b[i])//如果这根木棒被用过,寻找下一根
            continue;
        if(a[i]+cur>length)//如果选了这根木棒超过了规定的长度length,继续寻找下一根
            continue;
        b[i]=1;//标记这根木棒被用过
        if(dfs(now,cur+a[i],i+1))//将所选的这根木棒拼到目前拼上,继续拼接,从i+1开始寻找
            return true;
        b[i]=0;//将标记过的木棒释放
        if(cur==0||cur+a[i]==length )//如果这根木棒寻找第一根都失败或者这根木棒已经拼完,拼下一根的时候失败,那么就是寻找失败了
            return false;
        int j=i;
        while(j<n&&a[j]==a[i])   j++;//由于目前所选这根木棒没有拼接成功,所以跳过与目前所选的这根木棒长度所有长度相同的木棒
        i=j-1;
    }
    return false;
}

int main()
{
    while(cin>>n&&n)
    {
    	memset(b,0,sizeof(b));
		k=0,length=0,sum=0;
        for(int i=0;i<n;i++)
        {
            scanf("%d",&m);
            if(m>50)//跳过长度大于50的数据
                continue;
            a[k++]=m;
            sum+=m;
          }
          sort(a,a+k,greater<int>());
          length=a[0];//选出最长的一根,
          while(length)//从最长的一根开始寻找
          {
              if(sum%length==0&&dfs(0,0,0))//能整除再开始寻找
              {
                cout<<length<<endl;
                   break;
               }
                length++;//没找到就让长度加一继续寻找
          }
    }
    return 0;
}

  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值