Acwing 165.小猫爬山

算法标签:dfs+剪枝优化

题目链接:小猫爬山

题目大意:已知一辆缆车的最大承受重量和m只猫的重量,求最少需要多少量缆车

思路:按体重从大到小枚举每只小猫(优化搜索顺序),每只小猫有两种选择,可以选则加入之前的缆车,如果可以加入的话(可行性剪枝),也可以选择自己额外开一辆缆车。当枚举到最后一只的时候,更新一下res,如果搜索过程中,当前缆车数量已经>=res,直接返回(最优性剪枝)

那为什么按从大到小能优化搜索呢?

我的理解是:如果先搜大的,后面就只能搜小的,如果先搜小的话,后面即可以搜大的也可以搜小的,这样搜分支显然比先搜大的多很多,所以先搜大的能够优化搜索。

代码如下:

#include<bits/stdc++.h>
using namespace std;
#define sf(x) scanf("%lld",&x)
#define sff(x,y) scanf("%lld%lld",&x,&y)
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define pii pair<int,int> 
#define f first 
#define s second
#define int long long


const int N=20;
int m,maxd;
int w[N],sum[N],res=8888;

bool cmp(int a,int b)
{
    return a>b;
}

void dfs(int u,int now)
{
    if(now>=res)//最优性剪枝
        return ;
	if(u==m)
	{
		res=min(res,now);
		return;
	}
	//加到别的组
	for(int i=1;i<=now;i++)
	{
		if(sum[i]+w[u]<=maxd)//可行性剪枝
        {
			sum[i]+=w[u];
			dfs(u+1,now);
			sum[i]-=w[u];
		}
	}
	
	//自创一组
	sum[now+1]=w[u];
	dfs(u+1,++now);
	sum[now+1]=0;
}

signed main()
{
	sff(m,maxd);
	
	for(int i=0;i<m;i++) sf(w[i]);
	sort(w,w+m,cmp);//优化搜索顺序
	
	dfs(0,0);
	
	cout<<res;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值