算法题(105):小猫爬山

审题:

本题需要我们找出将n个小猫放在有限重的缆车上运下山所需的最小缆车数

时间复杂度分析:本题的数据量小于等于18,所以我们在做好剪枝的前提下可以使用深度优先搜索解题

思路:

方法一:dfs

搜索策略:将小猫一个个的放入缆车中,有两种放法:

第一种是放到当前已有缆车中,第二种是放到新的缆车中

剪枝策略:

剪枝1:可行性剪枝

我们需要在小猫重量+当前缆车中小猫总重小于等于限重时放入,若不满足就剪枝

剪枝2:最优化剪枝

在我们已经搜索过的放法中,最小缆车数会被放到answer,若answer小于当前的缆车数c,那么说明该条路线已经不用搜索了,最优情况也就是等于answer。

剪枝3:优化搜索顺序

优化1:先从体重较大的小猫开始放入,因为这样可以更快搜索出较小的answer

优化2:先考虑已有的缆车放入,再考虑开新缆车,也是服务于剪枝2的

解题:

#include<iostream>
#include<algorithm>
using namespace std;
const int N = 20;
int n, w;
int answer = N;
int c = 0;//当前车数
int cat[N], s[N];//cat负责记录猫的体重,s记录缆车当前负重

(1)main函数与compare函数

bool compare(int a,int b)//改变比较逻辑为降序
{
	return a > b;
}
int main()
{
	//录入数据
	cin >> n >> w;
	for (int i = 1; i <= n; i++)
	{
		cin >> cat[i];
	}
	//优化搜索顺序
	sort(cat + 1, cat + n + 1, compare);
	dfs(1);//传递猫的索引
	cout << answer << endl;
	return 0;
}

这里我们进行剪枝3的优化1:先从较重的猫开始放入。

所以我们通过compare函数,自己实现大数据优先的降序sort

(2)dfs

void dfs(int pos)
{
	//剪枝:最优化搜索
	if (c >= answer)
	{
		return;
	}
	//结束条件
	if (pos > n)
	{
		answer = c;
		return;
	}
	//优先搜索不开新车情况
	for (int i = 1; i <= c; i++)
	{
		//可行性剪枝
		if (cat[pos] + s[i] > w)
		{
			continue;
		}
		s[i] += cat[pos];
		dfs(pos + 1);
		s[i] -= cat[pos];
	}
	//开新车情况
	c++;
	s[c] = cat[pos];
	dfs(pos + 1);
	s[c] = 0;
	c--;
}

结束条件:之所以可以直接让c给到answer,是因为经过了剪枝最优化搜索的筛选,c一定是小于answer的,否则就被剪掉了

剪枝3:我们优先搜索不开新车的情况,所以把开新车情况放在for循环后,只有当所有旧的缆车都无法承载当前猫的体重时才会进入开新车的情况。

而所有的dfs搜索基本都涉及回退,有的是看情况回退,有的是一定回退,像这里这种搜索情况但是不记录具体方法的就是一定回退,所以我们在dfs出来后要还原数据

P10483 小猫爬山 - 洛谷

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值