IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 挑战性题目DSCT601:背包问题 -> 正文阅读

[数据结构与算法]挑战性题目DSCT601:背包问题

挑战性题目DSCT601:背包问题

问题描述

有一个容量为 V V V的背包,要求往背包中装入价值尽可能多的物品。这些物品分别有两个属性:体积 w w w和价值 v v v,且每种物品至多有一个,背包可以不被装满,求装入后的最大价值。

输入输出格式:

第一行为两个整数 N 、 V N、V NV,用空格隔开,表示背包的容量 V V V与物品的数量 N N N。接下来 N N N行每行由两个整数 w i w_i wi? v i v_i vi?组成,用空格隔开,表示物品i的体积和价值。请以printf()方式输出最大价值即可。

约定 0 < N , V ≤ 1000000 0 < N, V ≤ 1000000 0<N,V1000000,且 0 < w i , v i ≤ 4294967296 0 < wi,vi ≤ 4294967296 0<wi,vi4294967296

题解

讲个笑话:开学一个月,挑战题第一道是数位dp;快期末了,挑战题最后一道是背包问题。而这门课没有讲动态规划😅

还有个更好笑的, N × V = 1 0 12 N\times V=10^{12} N×V=1012的背包问题😅

基础的01背包问题,dp[i][j]表示枚举到第 i i i个物品且背包装下了体积为 j j j的物品时物品的最大价值。于是我们每次枚举物品,尝试用新的物品去更新每个体积的最大价值,那么转移方程就是
dp[i][j]=max(dp[i][j],dp[i-1][j-vi]+wi)

可以发现,每次转移时我们仅调用了下标为i-1的数组,因此可以采用滚动数组的办法,省掉一维的空间。需要注意因为每次更新仅会修改j更大的节点的值,所以我们不能正序访问,而需要倒序访问,否则该问题会变为完全背包问题。

这样,01背包的理论复杂度为 O ( N V ) O\left(NV\right) O(NV),看起来对于本题 10 6 {10}^6 106的数据规模并不够用,但是由于物品的体积 v i v_i vi?范围较大,倘若数据随机生成,则容量落在 10 6 {10}^6 106范围内的物品的期望个数为 10 6 × 10 6 4294967296 ≈ 233 {10}^6\times\frac{{10}^6}{4294967296}\approx233 106×4294967296106?233,所以只要做好判断,就可以AC此题。

代码

#pragma GCC optimize(2)
#include<cstdio>
#include<ctype.h>
#define LL long long
using namespace std;
const int M=1e6;
int N,V,w,v;
LL dp[M+5],ans,r;
char c;
inline char nc()
{
	static const int buflen=1e6;
	static char buf[buflen],*p1=buf,*p2=buf;
	return p1==p2&&(p2=(p1=buf)+fread(buf,1,buflen,stdin),p1==p2)?EOF:*p1++;
}
LL read(){for(r=0;!isdigit(c);c=nc());for(;isdigit(c);c=nc())r=(r<<1)+(r<<3)+c-'0';return r;}
void out(LL x){if(x>9)out(x/10);putchar(x%10+'0');}
int main(int argc,char* argv[])
{
    freopen(argv[1],"r",stdin);
    N=read(),V=read();
    for(int i=1;i<=N;++i)
    {
    	w=read(),v=read();
    	for(int j=V;j>=w;--j)
    	if(dp[j]<dp[j-w]+v)dp[j]=dp[j-w]+v;
    }
    out(dp[V]);
}

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-01-14 02:14:08  更:2022-01-14 02:14:43 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 18:31:51-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码