一、背包九讲总述
关于动态规划问题,最典型的就是背包九讲,先理解背包九讲后再总结关于动态规划的问题
1、01背包问题
2、完全背包问题
3、多重背包问题
4、混合背包问题
5、二维费用的背包问题
6、分组背包问题
7、背包问题求方案数
8、求背包问题的方案
9、有依赖的背包问题
往前6篇博文已经介绍了前6个问题,有需要的同学可以看一下!!
二、背包问题求方案数
背包问题求方案数:设背包容量为C,一共N件物品,每件物品重量为w[i],每件物品的价值为v[i],求将背包装满的方案总数。
故:对于01背包问题、完全背包问题和多重背包问题的方法都完全可以使用
接下来,01背包问题为例进行解答:
设背包容量为C,一共N件物品,且只可以取一次,每件物品重量为w[i],每件物品的价值为v[i],求将背包装满的方案总数。
类似求最大价值,我们也将问题抽象化:
1) 子问题定义:F[i][j]表示前i件物品中选取若干件物品放入剩余空间为j的背包中刚好把背包装满的方案总数。
2) 根据第i件物品体积和所剩背包容量大小进行决策
注意初始化条件为F[0][0]=1,即没有物品放入容量为0的背包刚好放满的方案数为1。
F[i-1][j]表示背包中不含第i种物品时把背包装满的方案,F[i-1][j-C[i]]表示包含第i种物品把背包装满的方案总数。所以,当j<C[i]时F[i][j] = F[i-1][j];当j >= C[i]时, F[i][j] = F[i-1][j-C[i]] + F[i-1][j],为什么是两者的和,因为F[i-1][j-C[i]]和F[i-1][j]都是[i][j]状态时把背包装满的方案,且两者互斥。
题目描述:
有 N 件物品和一个容量是 C 的背包。每件物品只能使用一次。
第 i 件物品的体积是 w[i],价值是 v[i]。
求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
输出 最优选法的方案数。注意答案可能很大,请输出答案模 pow(10,9)+7 的结果。
输入格式
第一行两个整数,N,C,用空格隔开,分别表示物品数量和背包容积。
接下来有 N 行,每行两个整数 w[i],v[i],用空格隔开,分别表示第 i 件物品的体积和价值。
输出格式
输出一个整数,表示 方案数 模 pow(10,9)+7 的结果。
#include<iostream>
#include<algorithm>
using namespace std;
const int mod = 1e9 + 7;
int v[100] = { 0 };//价值
int w[100] = { 0 };//重量
int f[100] = { 0 };
int main()
{
int N, C;
int n[100] = { 0 };
cout << "请输入物品数量和背包容量:" << endl;
cin >> N >> C;
for (int i = 1; i <= N; i++)
{
cout << "请输入第" << i <<"个物体的重量和价值:" << endl;
cin >> w[i] >> v[i];
}
f[0] = 1;//初始方案:没有物品放入容量为0的背包刚好放满的方案数为1
for (int i = 1; i <= N; i++)
{
for (int j = C; j >= w[i]; --j)
{
f[j] += f[j - w[i]];
}
}
cout <<"方案总数为:"<< f[C]%mod << endl;
system("pause");
return 0;
}
对于完全背包问题可以类推:
状态方程如下:
F[i-1][j]表示背包中不含第i种物品时把背包装满的方案,F[i][j-C[i]]表示至少包含一件第i种物品把背包装满的方案总数。所以,当j<C[i]时F[i][j] = F[i-1][j];当j >= C[i]时, F[i][j] = F[i][j-C[i]] + F[i-1][j],为什么是两者的和,因为F[i][j-C[i]]和F[i-1][j]都是[i][j]状态时把背包装满的方案,且两者互斥。