小猫爬山题解

小猫爬山

题目背景

翰翰和达达饲养了 N 只小猫,这天,小猫们要去爬山。
经历了千辛万苦,小猫们终于爬上了山顶,但是疲倦的它们再也不想徒步走下山了(呜咕>_<)。
翰翰和达达只好花钱让它们坐索道下山。

索道上的缆车最大承重量为 W,而 N 只小猫的重量分别是 C1、C2……CN。
当然,每辆缆车上的小猫的重量之和不能超过 W。

题目描述

翰翰和达达饲养了 N 只小猫,这天,小猫们要去爬山。
经历了千辛万苦,小猫们终于爬上了山顶,但是疲倦的它们再也不想徒步走下山了(呜咕>_<)。

翰翰和达达只好花钱让它们坐索道下山。

索道上的缆车最大承重量为 W,而 N 只小猫的重量分别是 C1、C2……CN。
当然,每辆缆车上的小猫的重量之和不能超过 W。

每租用一辆缆车,翰翰和达达就要付 1 美元,所以他们想知道,最少需要付多少美元才能把这 N 只小猫都运送下山?

输入格式

第 1 行:包含两个用空格隔开的整数,N 和 W。

第 2…N+1 行:每行一个整数,其中第 i+1 行的整数表示第 i 只小猫的重量 Ci。

输出格式

输出一个整数,表示最少需要多少美元,也就是最少需要多少辆缆车。

样例 #1

样例输入 #1

5 1996
1
2
1994
12
29

样例输出 #1

2

样例 #2

样例输入 #2

7 60816099
16726954
119926
46463304
60045456
25622459
32109683
1927806

样例输出 #2

4

提示

数据范围
1≤N≤18,1≤Ci≤W≤10^8

题解

思路

首先输入全部数据,其次把小猫一一分配到缆车里,记录下所有可能性中缆车数最小的那一个

输入

cin>>n>>w;//n:小猫总数 w:每辆缆车的最大承重
for(int i=0;i<n;i++)cin>>cat[i];//cat:每只小猫的重量

优化

我们可以把较重的小猫放在前面,轻的放在后面,以缩短程序的运行时间。例:

这里使用sort函数实现

sort(cat,cat+n,greater<int>());

深搜

在深搜函数中,我们需要实时关注两个变量:分好的小猫数量、现需缆车数量。当所有小猫都分好后,程序结束;而在程序结束时,需要记录下最小的缆车数

void dfs(int t,int r)//分好了t只小猫;现需r辆缆车
{
}

在这可以进行剪枝,如果当前的方案所需缆车数比记录中最小数要大,那么程序就没有必要继续进行了

if(r>ans)return;//减支 r:当前缆车数 ans:最小记录
if(t==n)//分完所有小猫
{
	ans=r;//更新最小缆车数,因为上面已经把大于的排除了,所以更新后的一定是相等或是小于的
	return;
}

然后枚举缆车,看看当前的小猫可以放进哪辆缆车

for(int i=0;i<r;i++)//枚举缆车
{
	if(car[i]+cat[t]<=w)//如果当前小猫进来后不超重
	{
		car[i]+=cat[t];//更新这辆缆车的重量
		f=1;//标记数组,表示不需要单独为这只小猫买一辆缆车
		dfs(t+1,r);//下一只
		car[i]-=cat[t];//还原重量
	}
}

如果现有的缆车都放不进这只小猫,那么就再买一辆

if(f==0)//都放不进
{
	car[r]=cat[t];//更新缆车重量
	dfs(t+1,r+1);//更新分好的小猫数和缆车数
	car[r]-=cat[t];//还原重量
}

完整代码

#include<bits/stdc++.h>
using namespace std;
const int maxn=20;
int n,w,cat[maxn],car[maxn],ans=maxn;//cat:小猫体重 car:缆车重量 ans:缆车最小值 
void dfs(int t,int r)
{
	int f=0;//标记数组,表示是否需要为当前小猫单独买一辆缆车 
	if(r>ans)return;//剪枝,如果当前方案的缆车数大于最小记录,结束 
	if(t==n)//分完所有小猫 
	{
		ans=r;//更新最小值 
		return;
	}
	for(int i=0;i<r;i++)//枚举缆车,看看这只小猫能放进哪辆缆车 
	{
		if(car[i]+cat[t]<=w)//如果小猫进去后不超重 
		{
			car[i]+=cat[t];//更新重量 
			f=1;//标记无需单独买缆车 
			dfs(t+1,r);//下一只 
			car[i]-=cat[t];//还原重量 
		}
	}
	if(f==0)//如果现有缆车都装不进去这只小猫 
	{
		car[r]=cat[t];//更新重量 
		dfs(t+1,r+1);//更新分好的小猫数和缆车数 
		car[r]-=cat[t];//还原重量 
	}
}
int main()
{
	cin>>n>>w;//n:小猫总数 w:单个缆车的最大承重 
	for(int i=0;i<n;i++)cin>>cat[i];//输入每只小猫的重量 
	sort(cat,cat+n,greater<int>());//把小猫按从重到轻排序,以缩短时间 
	dfs(0,0); 
	cout<<ans;//输出最小值 
	return 0;
} 
  • 12
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值