搜索-剪枝(木棒)

剪枝

剪枝,就是减小树规模,尽早排除搜索树中不必要的分支,也就是对搜索的优化。

以下是几种常见剪枝方法:

  1. 优化搜索顺序(比如下一题的木棒,优先尝试长的,长的不行,直接返回)
  2. 排除等效冗余(木棒中四种剪枝就是如此,几种分支等效,对一个进行搜索,失败直接返回)
  3. 可行性剪枝(可以看见的死胡同,可以直接返回)
  4. 最优化剪枝(记录最优解,此时花费超过最优解,可以直接返回,木棒:len是递增,先得出就是最优,就不用考虑这个了)
  5. 记忆化(记录每个状态的搜索结果,重复时,直接检索并返回)

AcWing 167. 木棒

思路

在上面的剪枝方法中已经简单提到了,这个题的剪枝。

下面是这个题的主要四个剪枝(代码中也有注释):

  1. 拼接时,按递减顺序加入,防重混乱
  2. 该长度拼接失败,后面再遇到,跳过
  3. 第一根就失败,直接返回
  4. 如果第一根恰好拼接成功,后面出现问题,len不符合,返回
代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int n,a[65],len,cnt,v[100];//v用来标记是否选择
bool dfs(int stick,int current,int pos)
{//拼装第stick根,当前长度为current,从pos处选择木棒
    if(stick>cnt) return true;//已经拼装好cnt根,搜索成功
    if(current==len) return dfs(stick+1,0,1);//长度=len,第stick已经拼装好
    int fail=0;//剪枝2:去重,相同长度不再判断
    for(int i=pos;i<=n;i++)//剪枝1:递减枚举,以防重复混乱
    {
        if(!v[i]&&current+a[i]<=len&&fail!=a[i])
        {
            v[i]=1;//标记此木棒已选
            if(dfs(stick,current+a[i],i+1)) return true;
//递归接着拼,直至stick>cnt,返回 true,if为真,返回true;
            fail=a[i]; //没能return true。a[i]不可拼接,记录一下
            v[i]=0;//取消标记
            if(current==0||current+a[i]==len)
            return false;
//剪枝3:current=0,连符合的第一段都找不到,直接返回
//剪枝4:current+a[i]==len,第一段拼好,后面出问题直接返回,因为拼接是从长到短选的,
//有点贪心的感觉
        }
        
    }return false;
    //所有分支都没合适的,失败
    
}
signed main()
{
	IOS
	while(cin>>n&&n)
	{
	    int sum=0;
	    for(int i=1;i<=n;i++){
	        cin>>a[i];
	        sum+=a[i];
	    }
	     
	    sort(a+1,a+n+1,greater<int>() );//先从最大的组合,确定顺序
	    for(len=a[1];len<=sum;len++)//从小到大判断,求的是最小len
	    {
	        if(sum%len) continue;
	        cnt=sum/len;  //确定了判断对象:长度为len,一共cnt根
	        memset(v,0,sizeof(v));//初始化为0,每一根都没选择
	        if(dfs(1,0,1)) break;//要拼接的第一根,当前长度为0,从a[1]开始选择      
	    } 
	    cout<<len<<'\n';
	}
	 
	
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值