[每日一题]:小猫爬山 题目: 样例: 题目链接: 侃侃: Code: 后记:

[每日一题]:小猫爬山
题目:
样例:
题目链接:
侃侃:
Code:
后记:

样例:

[每日一题]:小猫爬山
题目:
样例:
题目链接:
侃侃:
Code:
后记:

题目链接:

https://www.acwing.com/problem/content/167/

侃侃:

看一下这道题的数据范围,N <= 18,很小的数据范围,也就是说最多只需要 18 辆缆车就够了,
所以我们考虑去暴力去解决这道问题,对于每一只猫不同的组合,对应的缆车当然也会有所不同。

由于数据范围较小,我们可以去枚举所以的排列组合,说到排列组合,个人感觉用排列组合也是可以
的,最多只有 18!种方案,然后判断每种方案需要的缆车数量即可。
实际上我们用搜素也是去枚举各种方案,只是其中加了一些剪枝的操作,可以降低一些时间复杂度。

Code:

#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int maxn = 20;

int cat[maxn],cab[maxn]; // cat: 猫的重量 cab: 每台缆车容量 

int n,w;

int res = 0;

void DFS(int id,int cnt) {
	// 缆车数量最多 n 辆 
	if(cnt >= res) return ;
	// 所有猫都已经有归属 
	if(id == n + 1) {
		res = min(res,cnt);
		return ;
	}
	for(int i = 1; i <= cnt; i ++) {
		if(cat[id] + cab[i] <= w ) {
			cab[i] += cat[id];
			DFS(id + 1,cnt);
			// 回溯,也许租给另一只猫可以得到更小值 
			cab[i] -= cat[id];
		}
	}
	// 目前所有的缆车都无法容纳当前的猫,所以需要再租一辆 
	cnt ++;
	cab[cnt] = cat[id];
	DFS(id + 1,cnt);
	// 回溯,也许租给另一只猫更合适 
	cab[cnt] = 0;
}

int main(void) {
	scanf("%d%d",&n,&w);
	for(int i = 1; i <= n; i ++) {
		scanf("%d",&cat[i]);
	}
	// 最多只需要 n 辆车即可 
	res = n;
	DFS(1,0);
	printf("%d
",res);
	return 0;
} 

后记:

这类搜索题还是比较常见的,与图染色问题类似,都是已知一些内容,然后放东西,看当前的内容是否可以
容纳,如果无法容纳,就重新开辟空间。
感觉这种题对思维的帮助还是十分有用的,加油!