挑战性题目DSCT601:背包问题

本文介绍了一种解决背包问题的方法,使用动态规划中的01背包算法,并通过滚动数组优化空间复杂度。针对大规模数据,文章还提供了高效的实现技巧。

挑战性题目DSCT601:背包问题

问题描述

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

输入输出格式:

第一行为两个整数N、VN、VNV,用空格隔开,表示背包的容量VVV与物品的数量NNN。接下来NNN行每行由两个整数wiw_iwiviv_ivi组成,用空格隔开,表示物品i的体积和价值。请以printf()方式输出最大价值即可。

约定0<N,V≤10000000 < N, V ≤ 10000000<N,V1000000,且0<wi,vi≤42949672960 < wi,vi ≤ 42949672960<wi,vi4294967296

题解

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

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

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

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

这样,01背包的理论复杂度为O(NV)O\left(NV\right)O(NV),看起来对于本题106{10}^6106的数据规模并不够用,但是由于物品的体积viv_ivi范围较大,倘若数据随机生成,则容量落在106{10}^6106范围内的物品的期望个数为106×1064294967296≈233{10}^6\times\frac{{10}^6}{4294967296}\approx233106×4294967296106233,所以只要做好判断,就可以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]);
}

Lz变换 考 虑 一 个 离 散 状 态 连 续 时 间 的 马 尔 科 夫 过 程 (DSCT):X (t)Î{x1xK}t ³ 0 ,共有 K 个可能的状态 i , i = 1K 。 状 态 集 x ={x1xK} 、转 移 率 矩 阵 A =aij(t)ij = 1K 和初始状态概率分布 p0 就完整的 定义了该马尔科夫过程。其中 p0 定义如下: p0 =[p10 = Pr{X (0) = x1}pK0 = Pr{X (0) = xK}] 对 于 一 个 离 散 状 态 连 续 时 间 的 马 尔 科 夫 过 程 X (t) = xAp0 ,Lz变换的函数 u(ztp0) 定义为如下: L Z{X (t)}= u(ztp0) = å i = 1 K pi(t)zxi (3) 考虑一个最简单的单部件两状态系统。马尔科夫过 程 X (t) = xAp0 定义如下: 状态集 x ={x1x2}={01} 转移率矩阵 A =aij(t) = æ èç-μ μ ö ø ÷ λ -λ ,其中 λμ 分别为 失效率和修复率 初始状态 p0 =[p10p20] = [01] 由 dP(t) dt = P(t)A (2.2式) 得到微分方程组: ìïïíïïî dp1(t) dt = -μp1(t) + λp2(t) dp2(t) dt = μp1(t) - λp2(t) , (4) 初值条件: ìíî p1(0) = p10 = 0 p2(0) = p20 = 1 通过做拉普拉斯变换,可以求解得到结果如下: ìïïíïïî p1(t) = λ λ + μ - λ λ + μ exp{-(λ + μ)t} p2(t) = μ λ + μ + λ λ + μ exp{-(λ + μ)t} (5) 通过定义(3)式得到所给马尔科夫过程的Lz变换为: L z{X (t)}= å i = 1 2 pi(t)zxi = é ëê λ ù û ú λ + μ - λ λ + μ exp{-(λ + μ)t} z0 + éêë ùúû μ λ + μ + λ λ + μ exp{-(λ + μ)t} z1
最新发布
10-15
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ShadyPi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值