[每日一题]:小猫爬山
题目:
样例:
题目链接:
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\n",res);
return 0;
}
后记:
这类搜索题还是比较常见的,与图染色问题类似,都是已知一些内容,然后放东西,看当前的内容是否可以
容纳,如果无法容纳,就重新开辟空间。
感觉这种题对思维的帮助还是十分有用的,加油!
如果说年轻人未来是一场盛宴的话,那么我首先要有赴宴的资格。