01背包

整理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.

01背包 基础
Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u

Description

The aspiring Roy the Robber has seen a lot of American movies, and knows that the bad guys usually gets caught in the end, often because they become too greedy. He has decided to work in the lucrative business of bank robbery only for a short while, before retiring to a comfortable job at a university. 


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

The first line of input gives T, the number of cases. For each scenario, the first line of input gives a floating point number P, the probability Roy needs to be below, and an integer N, the number of banks he has plans for. Then follow N lines, where line j gives an integer Mj and a floating point number Pj . 
Bank j contains Mj millions, and the probability of getting caught from robbing it is Pj .
 

Output

For each test case, output a line with the maximum number of millions he can expect to get while the probability of getting caught is less than the limit set. 

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.

F - 01背包
Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u

Description

Many years ago , in Teddy’s hometown there was a man who was called “Bone Collector”. This man like to collect varies of bones , such as dog’s , cow’s , also he went to the grave … 
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

The first line contain a integer T , the number of cases. 
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

One integer per line representing the maximum of the total value (this number will be less than 2  31).
 

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.


01背包(就地滚动)
Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u

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;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值