ccxk
2024-09-09
点 赞
0
热 度
36
评 论
0

小猫爬山

文章摘要

智阅GPT

题目:小猫爬山

题目描述:
翰翰和达达饲养了 ​N 只小猫,这天,小猫们要去爬山。经历了千辛万苦,小猫们终于爬上了山顶,但是疲倦的它们再也不想徒步走下山了。翰翰和达达只好花钱让它们坐索道下山。索道上的缆车最大承重量为 ​W,而 ​N 只小猫的重量分别是 ​C_1, C_2, \dots, C_N。每辆缆车上的小猫的重量之和不能超过 ​W。每租用一辆缆车,翰翰和达达就要付 1 美元,求最少需要多少美元才能把这 ​N 只小猫都运送下山。

输入描述:

  • 第 1 行:两个用空格隔开的整数 ​N​W
  • 第 2 行到第 ​N+1 行:每行一个整数,表示每只小猫的重量 ​C_i

输出描述:
输出一个整数,表示最少需要多少美元,也就是最少需要多少辆缆车。

样例输入:

5 1996
1
2
1994
12
29

样例输出:

2

提示:
​1 \leq N \leq 18, ​1 \leq C_i \leq W \leq 10^8


思路:DFS

  1. DFS 函数部分:void dfs(int x, int k),其中 ​x 表示当前处理的小猫编号,​k 表示当前已经使用的缆车数量。

    • 如果当前使用的缆车数量 ​k 已经大于等于 ​minn(当前最小所需美元数),则返回(进行剪枝,提高效率)。
    • 如果已经处理完所有小猫,更新 ​minn 为当前所需缆车数量 ​k,并返回。
    • 尝试将当前小猫放入当前缆车,并递归调用 dfs 函数继续处理下一只小猫,处理完后将该小猫从当前缆车中移除。
    • 尝试将当前小猫单独放入一辆新的缆车,并递归调用 dfs 函数继续处理下一只小猫,处理完后将该小猫从当前缆车中移除。
  2. 主函数部分:

    • 排序:将小猫的重量按照从大到小排序,以便先处理重的小猫。
    • 调用 DFS:调用 dfs 函数从第一只小猫开始进行深度优先搜索,初始已用缆车数量为 0。
    • 输出结果:输出计算得到的最少所需美元数。

AC代码:

#include<bits/stdc++.h>
#define N 1001
using namespace std;
int w, n, car[N], cat[N], minn = 0x3f3f3f3f;
bool cmp(int x, int y) { return x > y; }

void dfs(int x, int k) {
    if (k >= minn) return;
    if (x == n + 1) {
        minn = min(minn, k);
        return;
    }
    for (int i = 1; i <= k; i++) {
        if (car[i] + cat[x] <= w) {
            car[i] += cat[x];
            dfs(x + 1, k);
            car[i] -= cat[x];
        }
    }
    car[k + 1] += cat[x];
    dfs(x + 1, k + 1);
    car[k + 1] -= cat[x];
}

int main() {
    cin >> n >> w;
    for (int i = 1; i <= n; i++) {
        cin >> cat[i];
    }
    sort(cat + 1, cat + 1 + n, cmp);
    dfs(1, 0);
    cout << minn;
    return 0;
}

时间复杂度: ​O(n!)
空间复杂度: ​O(n)


其他方法:状态压缩DP

  1. 将猫的数量设成二进制数(最多有 10 只)。
  2. ​f[i][j]​i 是缆车数量,​j 是当前已选择的小猫集合的状态。
  3. 动态转移方程:若当前猫能被放入缆车,则更新状态;否则,新开一辆缆车,状态转移。
  4. 最终输出最少缆车数。

AC代码:

#include<bits/stdc++.h>
#define N 1000001
using namespace std;
int n, W, w[N], f[20][N], ans = 0x3f3f3f3f;

int main() {
    cin >> n >> W;
    memset(f, 0x3f, sizeof f);
    for (int i = 1; i <= n; i++) {
        cin >> w[i];
    }
    f[1][0] = 0;
    for (int i = 1; i <= n; i++) {
        for (int j = 0; j <= (1 << n) - 1; j++) {
            if (f[i][j] != 0x3f3f3f3f) {
                for (int k = 1; k <= n; k++) {
                    if ((j | (1 << (k - 1))) != j && f[i][j] + w[k] <= W) {
                        f[i][j | (1 << (k - 1))] = min(f[i][j | (1 << (k - 1))], f[i][j] + w[k]);
                    } else {
                        f[i + 1][j | (1 << (k - 1))] = min(f[i + 1][j | (1 << (k - 1))], w[k]);
                    }
                }
            }
        }
    }
    for (int i = 1; i <= n; i++) {
        if (f[i][(1 << n) - 1] != 0x3f3f3f3f) {
            ans = min(ans, i);
        }
    }
    cout << ans;
    return 0;
}

用键盘敲击出的不只是字符,更是一段段生活的剪影、一个个心底的梦想。希望我的文字能像一束光,在您阅读的瞬间,照亮某个角落,带来一丝温暖与共鸣。

ccxk

站长

不具版权性
不具时效性

文章内容不具时效性。若文章内容有错误之处,请您批评指正。


目录

欢迎来到ccxk的站点,为您导航全站动态

26 文章数
5 分类数
6 评论数
15标签数
最近评论
ccxk

ccxk


hi

ccxk

ccxk


Hi

Camelaaa_

Camelaaa_


热门文章

访问统计