牛牛的背包问题(另类背包问题)

??:

题目描述

牛牛准备参加学校组织的春游, 出发前牛牛准备往背包里装入一些零食, 牛牛的背包容量为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种情况。

核??: 动态规划的核心就是合并状态,使搜索空间变小. 这个问题由于背包太大的缘故, 使用背包复杂度O(nm);很明显不行, 网上对这道题的做法是dfs, 说白了就是暴力枚举, 当这样的数据, n=30, m=29, n个糖果质量为1时, 运算次数会达到2^30次...总之题目数据不强, 怎么办呢...我是这样做的, 另类二分, 将数据非为两半, 分别暴力枚举俩个部分(2^15), 然后把两部分状态相加小于背包容量的方案加起来, 这样就好啦~~
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
struct node {
    LL val;
    LL cnt;
};
int n; LL v;
LL w[35];
vector<node> f(int l, int r) {
    vector<node> ans;
    int len=r-l+1;
    int base=1<<len;
    map <LL, int> mapp;
    for (int i=0;i<base;i++) {
        LL tsum=0;
        for (int k=0;k<len;k++)
            if (i&(1<<k))
                tsum+=w[k+l];
        mapp[tsum]++;
    }
    for (auto it: mapp) {
        node tmp={it.first, it.second};
        ans.push_back(tmp);
    }
    return ans;
}
int main()
{
    scanf("%d %lld",&n,&v);
    for (int i=1;i<=n;i++)
        scanf("%lld",&w[i]);
    vector<node> a1=f(1, n/2);
    vector<node> a2=f(n/2+1, n);
    for (int i=1;i<a2.size();i++)
        a2[i].cnt+=a2[i-1].cnt;
    int l1=a1.size();
    int j=a2.size()-1;
    LL ans=0;
    for (int i=0;i<l1;i++) {
        while (j>=0&&a1[i].val+a2[j].val>v) j--;
        if (j<0) break;
        ans+=a1[i].cnt*a2[j].cnt;
    }
    printf("%lld\n",ans);
    return 0;
}

原文地址:https://www.cnblogs.com/xidian-mao/p/11368388.html

时间: 2024-10-27 06:58:29

牛牛的背包问题(另类背包问题)的相关文章

背包问题:0/1背包问题 普通背包问题(贪心算法只适用于普通背包问题)

//sj和vj分别为第j项物品的体积和价值,W是总体积限制. //V[i,j]表示从前i项{u1,u2,…,un}中取出来的装入体积为j的背包的物品的最大价值. 第一种:0/1背包问题 最大化 ,受限于  1)若i=0或j=0,  V[i,j] = 0 2)若j<si, V[i,j] = V[i-1,j] 3)若i>0且j>=si, V[i,j] = Max{V[i-1,j],V[i-1,j-si]+vi} 第二种:背包问题:在选择物品i装入背包时,可以选择物品i的一部分,而不一定要全部

0-1 背包问题、背包问题、最优装载问题、哈夫曼编码,这几个问题的思想是什么?

0-1背包问题: 给定n种物品和一个背包.物品i的重量是Wi,其价值为Vi,背包的容量为C.应如何选择装入背包的物品,使得装入背包中物品的总价值最大? 在选择装入背包的物品时,对每种物品i只有2种选择,即装入背包或不装入背包.不能将物品i装入背包多次,也不能只装入部分的物品i. 背包问题: 与0-1背包问题类似,所不同的是在选择物品i装入背包时,可以选择物品i的一部分,而不一定要全部装入背包,1≤i≤n. 解决方法:求每个物品的价值重量比,即价值/重量.然后添加价值重量比最大的物品,添加结束如果

dp背包问题/01背包,完全背包,多重背包,/coin change算法求花硬币的种类数

一步一步循序渐进. Coin Change 具体思想:给你 N元,然后你有几种零钱S={S1,S2...,Sm} (每种零钱数量不限). 问:凑成N有多少种组合方式  即N=x1 * S1+x2*S2+...+xk*Sk (xk>=0,k=1,2..m) 设有f(x)中组合方式 有两种解答(自底向上回溯): 1.不用第m种货币   f(N,m-1) 2.用第m种货币 f(N-Sm,m) 总的组合方式为f(N,m)=f(N,m-1)+f(N-Sm,m) anything is nonsense,s

动态规划法——求解0-1背包问题

问题描述 0-1背包问题与背包问题(贪心法--背包问题)最大的不同就是背包问题的子问题彼此之间没有联系,所以只要找出解决方法,然后用贪心算法,取得局部最优解就ok了,但是0-1背包问题更复杂,因为物品不可再分,导致了子问题之间是有联系的. 问题分析 1,刻画背包问题最优解的结构 2,数学描述 伪代码解读 当上段代码运算完成之后,对于C[i,w]的表: 然后根据上面构造的表,求最优解: 小结 动态规划法在判断是否含有第i个物品时,通过判断C[I,w]是否等于C[i-1,w]来得出是否含有第i个物品

【转载】0-1背包问题

0-1背包问题 0-1背包问题: 有N件物品和一个容量为V的背包.第i件物品的费用是c[i],价值是w[i].求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大. 这个问题的特点是:每种物品只有一件,可以选择放或者不放. 算法基本思想: 利用动态规划思想 ,子问题为:f[i][v]表示前i件物品恰放入一个容量为v的背包可以获得的最大价值. 其状态转移方程是:f[i][v]=max{f[i-1][v],f[i-1][v-c[i]]+w[i]}    //这个方程非常重要,基

数据结构之贪心算法(背包问题的思考)-(十)

贪心策略.关于贪心算法的思考,思考过程都放在代码中了. package com.lip.datastructure; /** *贪心算法:装箱问题的思考 * @author Lip *装箱问题可以是时间调问题的延伸,当一个箱子没有容积限制,那么就是时间调度问题 *在时间调度问题中:存在两个可以讨论的问题.1.平均最短时间 2.总的最短时间 *这两个问题都和装箱问题中问题如此类似. */ /* * 上面是我理解的装箱问题,本来是想说背包问题的 * 背包问题的描述:有N件物品和一个容量为V的背包.第

动态规划——背包问题

背包问题是一类非常典型的动态规划问题,包括多种类型(01背包.完全背包.多重背包.混合背包.二维费用背包等)其基本类型为01背包问题. 一.01背包问题 N件物品,每件物品的重量和价值分别为 w[i], v[i], 把这些物品放到一个容量为W的背包中,求背包中物品的价值的最大值. 形式化定义:  分析     最直观的思路是枚举背包中出现的所有可能的物品组合,然后计算它们的价值和,求最大值.如果直接采用递归搜索,则会有大量的冗余,通过记忆化搜索的方式可以进行改进(记忆 max[i][w], 前i

动态规划-多重背包问题

0-1背包问题 完全背包问题 多重背包问题是0-1背包问题和完全背包问题的综合体,可以描述如下:从n种物品向容积为V的背包装入,其中每种物品的体积为w,价值为v,数量为k,问装入的最大价值总和? 我们知道0-1背包问题是背包问题的基础,所以在解决多重背包问题的时候,要将多重背包向0-1背包上进行转换.在多重背包问题中,每种物品有k个,可以将每种物品看作k种,这样就可以使用0-1背包的算法.但是,这样会增加数据的规模.因为该算法的时间复杂度为O(V*∑ni=1ki),所以要降低每种物品的数量ki.

C# 0-1背包问题

0-1背包问题 0-1背包问题基本思想: p[i,j]表示在前面i个物品总价值为j时的价值最大值.str[i, j]表示在前面i个物品总价值为j时的价值最大值时的物品重量串. i=0 或者j=0时: p[i, j] = 0; str[i, j] = ""; 第i件物品的在重量小于j时能够放入背包 p[i, j] = p[i - 1, j - w[i - 1]] + v[i - 1] > p[i - 1, j] ? p[i - 1, j - w[i - 1]] + v[i - 1]