一、题目查看
P10483 小猫爬山 - 洛谷
二、解题思路
我们将采取递归 + 剪枝的思想:
sum数组存放每辆车当前载重。
每次新考虑一只小猫时,我们尝试把它放进每个可以放进的缆车中(需要回溯)
cppfor (int i = 0; i < k; i++) { if (sum[i] + c[u] <= w) { sum[i] += c[u]; dfs(u + 1, k); sum[i] -= c[u]; } }
我们还要再尝试为它单独新开一辆缆车,不然会错(也要回溯)
cppsum[k] = c[u]; dfs(u + 1, k + 1); // 再开一个缆车 sum[k] = 0;
最后我们需要更新答案和剪枝
cppif (k >= ans) return; // 如果缆车数量不如当前最佳答案直接剪枝 if (u == n) ans = k; // 小猫都装完了
三、代码
cpp#include <bits/stdc++.h> using namespace std; const int N = 20; int c[N], sum[N]; int n, w, ans; void dfs(int u, int k) { // u = 第 u 只小猫, k = 缆车数量 if (k >= ans) return; // 如果缆车数量不如当前最佳答案直接剪枝 if (u == n) ans = k; // 小猫都装完了 for (int i = 0; i < k; i++) { if (sum[i] + c[u] <= w) { sum[i] += c[u]; dfs(u + 1, k); sum[i] -= c[u]; } } sum[k] = c[u]; dfs(u + 1, k + 1); // 再开一个缆车 sum[k] = 0; } int main() { cin >> n >> w; ans = n; for (int i = 0; i < n; i++) { cin >> c[i]; } dfs(0, 0); cout << ans; return 0; }
四、测试结果