Files
python/TangDou/AcWing/JianZhi/165.md
HuangHai 1f397eca87 'commit'
2025-08-30 18:35:01 +08:00

93 lines
2.4 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

## [$AcWing$ $165$ 小猫爬山](https://www.acwing.com/problem/content/167/)
### 一、题目描述
翰翰和达达饲养了 $N$ 只小猫,这天,小猫们要去爬山。
经历了千辛万苦,小猫们终于爬上了山顶,但是疲倦的它们再也不想徒步走下山了(呜咕>_<)。
翰翰和达达只好花钱让它们坐索道下山。
索道上的缆车最大承重量为 $W$,而 $N$ 只小猫的重量分别是 $C_1、C_2……C_N$。
当然,每辆缆车上的小猫的重量之和不能超过 $W$。
每租用一辆缆车,翰翰和达达就要付 $1$ 美元,所以他们想知道,**最少** 需要付多少美元才能把这 $N$ 只小猫都运送下山?
**输入格式**
第 $1$ 行:包含两个用空格隔开的整数,$N$ 和 $W$。
第 $2..N+1$ 行:每行一个整数,其中第 $i+1$ 行的整数表示第 $i$ 只小猫的重量 $C_i$。
**输出格式**
输出一个整数,表示最少需要多少美元,也就是最少需要多少辆缆车。
**数据范围**
$1≤N≤18,1≤Ci≤W≤10^8$
**输入样例**:
```cpp {.line-numbers}
5 1996
1
2
1994
12
29
```
**输出样例**:
```cpp {.line-numbers}
2
```
### 二、实现代码
```cpp {.line-numbers}
#include <bits/stdc++.h>
using namespace std;
const int N = 20;
int n, m;
int w[N];
int sum[N];
int ans = N;
void dfs(int u, int len) {
// 最优性剪枝
if (len >= ans) return;
if (u == n + 1) { //走完
ans = len; //更新答案
return;
}
for (int i = 0; i < len; i++)
if (sum[i] + w[u] <= m) { //能放下的情况
sum[i] += w[u]; //放一下试试
dfs(u + 1, len); //下一只小猫,缆车没有增加
sum[i] -= w[u]; //回溯
}
// 新开一辆车
sum[len] += w[u];
dfs(u + 1, len + 1);
sum[len] -= w[u]; // 恢复现场
}
int main() {
cin >> n >> m;
for (int i = 1; i <= n; i++) cin >> w[i];
// 优化搜索顺序 21ms
// 不加优化搜索顺序 88ms
// Q:为什么可以采用这样的优化策略?
// A: dfs搜索的顺序很关键,很玄学,本着有矛盾先暴露,将一些分枝尽早结束,提前返回,可以提高搜索效率 
sort(w + 1, w + 1 + n, greater<int>());
dfs(1, 0);
cout<< ans <<endl;
return 0;
}
```