整理01背包前,先将基本背包问题及其解法列出:
背包问题
①01背包
有n 种不同的物品,每个物品有两个属性,size 体积,value 价值,现在给一个容量为 x 的背包,问最多可带走多少价值的物品。
int f[x+1]; //f[x] 表示背包容量为x 时的最大价值
for (int i=0; i<n; i++)
for (int j=x; j>=size[i]; j--)
f[j] = max(f[j], f[j-size[i]]+value[i]);
②完全背包
如果物品不计件数,就是每个物品不只一件的话,稍微改下即可
for (int i=0; i<n; i++)
for (int j=size[i]; j<=w; j++)
f[j] = max(f[j], f[j-size[i]]+value[i]);
f[w] 即为所求
初始化分两种情况:
1、如果背包要求正好装满则初始化 f[0] = 0, f[1~w] = -INF;
2、如果不需要正好装满 f[0~v] = 0;
③多重背包,将一件多种利用二进制转化为多种一件:(定理:一个正整数n可以被分解成1,2,4,…,2^(k-1),n-2^k+1(k是满足n-2^k+1>0的最大整
数)的形式,且1~n之内的所有整数均可以唯一表示成1,2,4,…,2^(k-1),n-2^k+1中某几个数的和的形式。)
int n; //输入有多少种物品
int c; //每种物品有多少件
int v; //每种物品的价值
int s; //每种物品的尺寸
int count = 0; //分解后可得到多少种物品
int value[MAX]; //用来保存分解后的物品价值
int size[MAX]; //用来保存分解后物品体积
scanf("%d", &n); //先输入有多少种物品,接下来对每种物品进行分解
while (n--) //接下来输入n中这个物品
{
scanf("%d%d%d", &c, &s, &v); //输入每种物品的数目和价值
for (int k=1; k<=c; k<<=1) //<<右移 相当于乘二
{
value[count] = k*v;
size[count++] = k*s;
c -= k;
}
if (c > 0)
{
value[count] = c*v;
size[count++] = c*s;
}
}
接下来用count 代替 n 就和01 背包问题完全一样了 。
1.
Description

For a few months now, Roy has been assessing the security of various banks and the amount of cash they hold. He wants to make a calculated risk, and grab as much money as possible.
His mother, Ola, has decided upon a tolerable probability of getting caught. She feels that he is safe enough if the banks he robs together give a probability less than this.
Input
Bank j contains Mj millions, and the probability of getting caught from robbing it is Pj .
Output
Notes and Constraints
0 < T <= 100
0.0 <= P <= 1.0
0 < N <= 100
0 < Mj <= 100
0.0 <= Pj <= 1.0
A bank goes bankrupt if it is robbed, and you may assume that all probabilities are independent as the police have very low funds.
Sample Input
3 0.04 3 1 0.02 2 0.03 3 0.05 0.06 3 2 0.03 2 0.03 3 0.05 0.10 3 1 0.03 2 0.02 3 0.05
Sample Output
2 4 6
题意大概是:一个小偷去银行抢劫之前进行了一番被捕概率分析:转化为背包,以第一个输入为例,背包体积为0.04,有三件物品,前者是物品的价值,后者使其费用,要怎样
装使其价值最大。
此题特殊点,与体积相关的都是小数,带来诸多不便。
c++.背包.01背包
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <iomanip>
#include <cmath>
#include <algorithm>
using namespace std;
const int MaxN = 10005;
const double eps = 1e-8;
int t, n, v[MaxN];
double P, p[MaxN], dp[MaxN];
void solve()
{
scanf("%lf%d", &P, &n);
P = 1.0 - P;
int sum = 0;
for (int i = 0; i < n; i++)
{
scanf("%d%lf", &v[i], &p[i]);
p[i] = 1.0 - p[i]; sum += v[i];
}
memset(dp, 0, sizeof(dp));
dp[0] = 1.0;
for (int i = 0; i < n; i++)
for (int j = sum; j >= v[i]; j--)
dp[j]=max(dp[j], dp[j-v[i]] * p[i]);
for (int i = sum; i >= 0; i--)
if (dp[i] - P > eps)
{
printf("%d\n", i); break;
}
}
int main()
{
scanf("%d", &t);
while (t--) solve();
return 0;
}
2.
Description
The bone collector had a big bag with a volume of V ,and along his trip of collecting there are a lot of bones , obviously , different bone has different value and different volume, now given the each bone’s value along his trip , can you calculate out the maximum of the total value the bone collector can get ?

Input
Followed by T cases , each case three lines , the first line contain two integer N , V, (N <= 1000 , V <= 1000 )representing the number of bones and the volume of his bag. And the second line contain N integers representing the value of each bone. The third line contain N integers representing the volume of each bone.
Output
Sample Input
1 5 10 1 2 3 4 5 5 4 3 2 1
Sample Output
14
题目大概意思是:某个人去捡骨头,怎样使其价值最大?
1
5 10//5个物体,背包为十个体积
1 2 3 4 5//每个物体的价值
5 4 3 2 1 //每个物体的费用
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define maxn 1005
int N,n,V,i,j;
int c[maxn],v[maxn],dp[maxn];
void solve()
{
memset(dp,0,sizeof(dp));
scanf("%d%d",&n,&V);
for( i=0;i<n;i++) scanf("%d",&v[i]);
for( i=0;i<n;i++) scanf("%d",&c[i]);
for( i=0;i<n;i++)
for(j=V;j>=c[i];j--)
{
dp[j]=max(dp[j],dp[j-c[i]]+v[i]);
}
printf("%d\n",dp[V]);
}
int main()
{
scanf("%d",&N);
while(N--) solve();
return 0;
}
3.
Description
Bessie has gone to the mall's jewelry store and spies a charm bracelet. Of course, she'd like to fill it with the best charms possible from the N (1 ≤ N≤ 3,402) available charms. Each charm i in the supplied list has a weight Wi (1 ≤ Wi ≤ 400), a 'desirability' factor Di (1 ≤ Di ≤ 100), and can be used at most once. Bessie can only support a charm bracelet whose weight is no more than M (1 ≤ M ≤ 12,880).
Given that weight limit as a constraint and a list of the charms with their weights and desirability rating, deduce the maximum possible sum of ratings.
Input
* Line 1: Two space-separated integers: N and M
* Lines 2..N+1: Line i+1 describes charm i with two space-separated integers: Wi and Di
Output
* Line 1: A single integer that is the greatest sum of charm desirabilities that can be achieved given the weight constraints
Sample Input
4 6 1 4 2 6 3 12 2 7
Sample Output
23
珠宝问题,和上面的一样,只不过数组要开打一点
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define maxn 100005
int n,M,i,j;
int w[maxn],d[maxn],dp[maxn];
void solve()
{
memset(dp,0,sizeof(dp));
scanf("%d%d",&n,&M);
for( i=0;i<n;i++)
scanf("%d%d",&w[i],&d[i]);
for( i=0;i<n;i++)
for(j=M;j>=w[i];j--)
{
dp[j]=max(dp[j],dp[j-w[i]]+d[i]);
}
printf("%d\n",dp[M]);
}
int main()
{
solve();
return 0;
}