AcWing 278. 数字组合(01背包问题求取方案数)

本文介绍了如何使用闫氏动态规划方法解决01背包问题,提供了两种代码版本对比,包括二维朴素代码和一维优化代码,并强调了初始化和边界条件的重要性。时间复杂度为O(nm),适用于求解从有限物品中选取部分组合,使得总价值不超过一定限制的方案数。
部署运行你感兴趣的模型镜像

在这里插入图片描述
在这里插入图片描述
题意:

01背包求方案数

思路:

闫氏dp分析法

在这里插入图片描述
注意:

初始化的时候,dp[0][0]代表从前0个物品选出总体积恰好是0的方案数,显然为1,而dp[0][1]、dp[0][2]、dp[0][3]等代表从前0个物品中选出总体积恰好是i(i=1、2、3…)的方案数,显然是不存在的,所以置为0。

时间复杂度:

O(nm)

二维朴素代码

#include<bits/stdc++.h>

using namespace std;
const int N = 110, M = 1e4+10;
int n, m;
int dp[N][M];

int main()
{
        cin>>n>>m;
        //初始化
        dp[0][0] = 1;
        for(int j=1;j<=m;++j)  dp[0][j] = 0;
        
        for(int i=1;i<=n;++i)
        {
                int a;
                cin>>a;
                for(int j=0;j<=m;++j)
                {
                        if(j<a) dp[i][j] = dp[i-1][j];
                        else dp[i][j] = dp[i-1][j]+dp[i-1][j-a];
                }
        }
        cout<<dp[n][m]<<endl;
        
        return 0;
}

一维优化代码

#include<bits/stdc++.h>

using namespace std;
const int N = 1e4+10;
int n, m;
int dp[N];

int main()
{
        cin>>n>>m;
        //初始化
        dp[0] = 1;
        for(int j=1;j<=m;++j)  dp[j] = 0;
        
        for(int i=1;i<=n;++i)
        {
                int a;
                cin>>a;
                for(int j=m;j>=a;--j)
                {
                        dp[j] += dp[j-a];
                }
        }
        cout<<dp[m]<<endl;
        
        return 0;
}

您可能感兴趣的与本文相关的镜像

ACE-Step

ACE-Step

音乐合成
ACE-Step

ACE-Step是由中国团队阶跃星辰(StepFun)与ACE Studio联手打造的开源音乐生成模型。 它拥有3.5B参数量,支持快速高质量生成、强可控性和易于拓展的特点。 最厉害的是,它可以生成多种语言的歌曲,包括但不限于中文、英文、日文等19种语言

AcWing 10题有依赖的背包问题具有一定特点,有 `N` 个物品和容量为 `V` 的背包,物品间存在依赖关系且构成树状,选择一个物品时必须选择其父节点,需找出使物品总体积不超背包容量且总价值最大的方案并输出最大价值 [^4]。 ### 思路 在树形背包问题里,可将动态规划的状态定义为当前节点以及是否选择了当前节点的物品,状态转移需考虑从当前节点的父节点和子节点转移过来的情况,还有当前节点是否选择物品 [^2]。 ### 代码实现 ```cpp #include<iostream> #include<vector> using namespace std; int f[110][110];//f[x][v]表达选择以x为子树的物品,在容量不超过v时所获得的最大价值 vector<int> g[110]; int v[110],w[110]; int n,m,root; int dfs(int x) { for(int i=v[x];i<=m;i++) f[x][i]=w[x];//点x必须选,所以初始化f[x][v[x] ~ m]= w[x] for(int i=0;i<g[x].size();i++) { int y=g[x][i]; dfs(y); for(int j=m;j>=v[x];j--)//j的范围为v[x]~m, 小于v[x]无法选择以x为子树的物品 { for(int k=0;k<=j-v[x];k++)//分给子树y的空间不能大于j-v[x],不然都无法选根物品x { f[x][j]=max(f[x][j],f[x][j-k]+f[y][k]); } } } } int main() { cin>>n>>m; for(int i=1;i<=n;i++) { int fa; cin>>v[i]>>w[i]>>fa; if(fa==-1) root=i; else g[fa].push_back(i); } dfs(root); cout<<f[root][m]; return 0; } ``` ### 代码解释 - `f[x][v]` 表示选择以 `x` 为子树的物品,在容量不超过 `v` 时所获得的最大价值。 - 初始化 `f[x][i]`(`i` 从 `v[x]` 到 `m`)为 `w[x]`,因为点 `x` 必须选。 - 递归遍历 `x` 的子节点 `y`,在更新 `f[x][j]` 时,需保证 `j` 从 `v[x]` 到 `m`,且分给子树 `y` 的空间 `k` 不大于 `j - v[x]`,以确保能选根物品 `x`。 ### 复杂度分析 - 时间复杂度:由于要遍历每个节点及其子节点,并且在每个节点处进行容量的枚举,时间复杂度为 $O(N * V^2)$,其中 `N` 是物品数量,`V` 是背包容量。 - 空间复杂度:主要用于存储动态规划数组和树的邻接表,空间复杂度为 $O(N * V)$。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值