深搜9:【SSL】1648.登山——2021-05-02第三更

深搜9:【SSL】1648.登山

题目:

题目描述

小b周末和同学共 n 人去爬山,等爬到山顶的时候大家已经累的不想再走路下山了,于是决定乘坐缆车下山。

每辆缆车的最大载重量为 w,现在已知所有同学的体重,请问至少需要多少辆缆车才能将他们全部运送下山?

输入

第1行:包含两个用空格隔开的整数,n 和 w。
接下来n行,表示每位同学的体重c。

1≤n≤18
1≤ci≤w≤10^8

输出

一个整数,表示最少需要的缆车数。

样例

输入样例
5 1996
1
2
1994
12
29

输出样例
2

思路:

这道题其实我一开始是想每个人都有两种方法,进缆车或不进缆车,不进当前的缆车那就再等后面的缆车,但这样的话就会超时,因为这样做一个人可能会一直不进缆车,那就死循环了。
如果是这样的话,那该怎么搜索呢?
其实,我们可以开一个数组来记录每一辆缆车的当前状况,从1循环到x(缆车数量),如果当前缆车可以放a[p]这个人的话,就放进去试一试,或者让他自己开1辆新的缆车,最后找到用车数量最少的方案就行了。
但看一下题目,最多有18个人,18的18次方这已经远远超过1亿了,必定会超时,那有什么剪枝方法?
其实剪枝方法有很多,这里列举一个最万能的:当目前所用的缆车数≥我目前已知的最小答案,那么就return。

代码:

#include<bits/stdc++.h>
using namespace std;
int n,w,a[20],lc[20],ans=100;
bool v[20];

void dfs(int p,int sl)
{
	if(p>n)
	{
		ans=min(ans,sl);
		return ;
	}
	if(sl>=ans)
		return ;
	for(int i=1;i<=sl;i++)
	{
		if(v[i]||a[p]+lc[i]>w)
			continue;
		lc[i]+=a[p];
		if(lc[i]==w)
			v[i]=true;
		dfs(p+1,sl);
		lc[i]-=a[p];
		v[i]=false;
	}
	sl++;
	lc[sl]=a[p];
	dfs(p+1,sl);
}
int main()
{
	cin>>n>>w;
	for(int i=1;i<=n;i++)
		cin>>a[i];
	dfs(1,1);
	cout<<ans;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值