牛牛的背包

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/HaloTrriger/article/details/82351836

链接:https://www.nowcoder.com/questionTerminal/bf877f837467488692be703735db84e6
来源:牛客网

牛牛准备参加学校组织的春游, 出发前牛牛准备往背包里装入一些零食, 牛牛的背包容量为w。
牛牛家里一共有n袋零食, 第i袋零食体积为v[i]。
牛牛想知道在总体积不超过背包容量的情况下,他一共有多少种零食放法(总体积为0也算一种放法)。

输入描述:

输入包括两行
第一行为两个正整数n和w(1 <= n <= 30, 1 <= w <= 2 * 10^9),表示零食的数量和背包的容量。
第二行n个正整数v[i](0 <= v[i] <= 10^9),表示每袋零食的体积。

输出描述:

输出一个正整数, 表示牛牛一共有多少种零食放法。

示例1

输入
3 10
1 2 4

输出
8

说明

三种零食总体积小于10,于是每种零食有放入和不放入两种情况,一共有2*2*2 = 8种情况。

思路:

类似从第一个数开始,选第一个数判断是否选取,依次第二个,第三个,第四个…;从第二个开始,判断是否选第三个,第四个…等等
这就用到深搜算法,一直向下递归,当前节点不满足,回退到上一节点相邻接点继续递归。
此题不同的是,对数据进行排序后,优化深搜深度。从第一个数开始,判断当前数字是否符合,然后向后面的数字累加判断是否超出背包容量大小,符合则让方法数+1;不符合后,当前递归结束,从第二数开始新一轮判断。直到把数组元素遍历完毕。

C++代码

#include<iostream>
#include<algorithm>
using namespace std;
int methodCount = 1;

void DFS(long long v[], int size, long long w,long long curSum, int pos)
{
    if (curSum <= w)
    {
        ++methodCount;
        for (int i = pos + 1; i < size; ++i)
            DFS(v, size, w, curSum+v[i], i);
    }
    else
        return;
}

int main()
{
    int n;
    long long w;
    long long v[30];
    long long sum = 0;
    cin >> n >> w;
    for (int i = 0; i < n; ++i)
    {
        cin >> v[i];
        sum += v[i];
    }
    //深度优先遍历,访问每个节点的下面的节点是否也符合条件
    //符合条件继续向下,不符合,回到上一层
    if (sum <= w)
        methodCount = 1 << n;
    else//对每个零食体积进行深搜
    {
        sort(v, v + n);
        for (int i = 0; i < n; ++i)
            DFS(v, n, w,v[i],i);
    }
        cout << methodCount << endl;
}

缺点:毕竟用的是递归,时间复杂度O(n^n)。
如果数字过多且物品体积总和大于背包容量,可能花费和长时间。

有什么不懂的或建议欢迎提问或指出,谢谢

猜你喜欢

转载自blog.csdn.net/HaloTrriger/article/details/82351836