背包专题(持续更新)

POJ 3624 Charm Bracelet 

题目链接:http://poj.org/problem?id=3624

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

题解:01背包
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <cstring>
 5 #include <string>
 6 using namespace std;
 7 int dp[200005];
 8 int main()
 9 {
10     int n,m;
11     while(cin>>n>>m){
12         int x,y;
13         memset(dp,0,sizeof(dp));
14         for(int i=0;i<n;i++){
15             cin>>x>>y;
16             for(int j=m;j>=x;j--){
17                 dp[j]=max(dp[j],dp[j-x]+y);
18             }
19         }
20         cout<<dp[m]<<endl;
21     }
22     return 0;
23 }
View Code

HDU 2602 Bone Collecter

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2602

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 ? 

InputThe 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.OutputOne 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

题解:01背包
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <cstring>
 5 #include <string>
 6 using namespace std;
 7 int dp[200005];
 8 int a[1001];
 9 int b[1001];
10 int main()
11 {
12     int n,v,t;
13     cin>>t;
14     while(t--){
15         cin>>n>>v;
16         memset(dp,0,sizeof(dp));
17         for(int i=0;i<n;i++)
18             cin>>a[i];
19         for(int i=0;i<n;i++)
20             cin>>b[i];
21         for(int i=0;i<n;i++){
22             for(int j=v;j>=b[i];j--){
23                 dp[j]=max(dp[j],dp[j-b[i]]+a[i]);
24             }
25         }
26         cout<<dp[v]<<endl;
27     }
28     return 0;
29 }
View Code

HDU 2546 饭卡

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2546

电子科大本部食堂的饭卡有一种很诡异的设计,即在购买之前判断余额。如果购买一个商品之前,卡上的剩余金额大于或等于5元,就一定可以购买成功(即使购买后卡上余额为负),否则无法购买(即使金额足够)。所以大家都希望尽量使卡上的余额最少。 
某天,食堂中有n种菜出售,每种菜可购买一次。已知每种菜的价格以及卡上的余额,问最少可使卡上的余额为多少。 

Input多组数据。对于每组数据: 
第一行为正整数n,表示菜的数量。n<=1000。 
第二行包括n个正整数,表示每种菜的价格。价格不超过50。 
第三行包括一个正整数m,表示卡上的余额。m<=1000。 

n=0表示数据结束。 
Output对于每组输入,输出一行,包含一个整数,表示卡上可能的最小余额。Sample Input

1
50
5
10
1 2 3 2 1 1 2 3 2 1
50
0

Sample Output

-45
32

题解:01背包变形
 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <string.h>
 4 #include <algorithm>
 5 using namespace std;
 6 int dp[1010];
 7 int val[1010];
 8 int main()
 9 {
10     int n,i,j,m;
11     while(cin>>n&&n){
12         memset(dp,0,sizeof(dp));
13         memset(val,0,sizeof(val));
14         for(int i=0;i<n;i++)
15             cin>>val[i];
16         cin>>m;
17         if(m<5) {
18             cout<<m<<endl;
19             continue;
20         }
21         sort(val,val+n);
22         int maxn=val[n-1];
23         m-=5;
24         if(m>=val[0]){
25             for(int i=0;i<n-1;++i){
26                 for(j=m;j>=val[i];--j){
27                     dp[j]=max(dp[j],dp[j-val[i]]+val[i]);
28                 }
29             }
30         }
31         cout<<m+5-dp[m]-maxn<<endl;
32     }
33     return 0;
34 }

HDU 2955 Robberies

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.

InputThe 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 .OutputFor 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

题解:

最重要的是找动态转移方程,可以将所用银行里的钱看作背包容量,每一家银行的钱看作重量,

不被抓到的概率看作价值,则转移方程为:dp[ j ]=max( dp[ j ] , dp[ j - bag[ i ].v]*( 1- bag[ i ].p ) );

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <cstring>
 5 #include <string>
 6 using namespace std;
 7 double dp[10010];
 8 struct Bag
 9 {
10     int v;
11     double p;
12 }bag[10010];
13 int main()
14 {
15     int n,t;
16     double p;
17     cin>>t;
18     while(t--){
19         cin>>p>>n;
20         int sum=0;
21         for(int i=0;i<n;i++){
22             cin>>bag[i].v>>bag[i].p;
23             sum+=bag[i].v;
24         }
25         memset(dp,0,sizeof(dp));
26         dp[0]=1;
27         for(int i=0;i<n;i++){
28             for(int j=sum;j>=bag[i].v;j--){
29                 dp[j]=max(dp[j],dp[j-bag[i].v]*(1-bag[i].p));
30             }
31         }
32         for(int i=sum;i>=0;i--){
33             if(dp[i]>1-p){
34                 cout<<i<<endl;
35                 break;
36             }
37         }
38     }
39     return 0;
40 }

UVA 562 Dividing coins

题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=503

题解:最重要的是找动态转移方程,可以将所用银行里的钱看作背包容量,每一家银行的钱看作重量,

不被抓到的概率看作价值,则转移方程为:dp[ j ]=max( dp[ j ] , dp[ j - bag[ i ].v]*( 1- bag[ i ].p ) );
*/

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <cstring>
 5 #include <string>
 6 using namespace std;
 7 double dp[10010];
 8 struct Bag
 9 {
10     int v;
11     double p;
12 }bag[10010];
13 int main()
14 {
15     int n,t;
16     double p;
17     cin>>t;
18     while(t--){
19         cin>>p>>n;
20         int sum=0;
21         for(int i=0;i<n;i++){
22             cin>>bag[i].v>>bag[i].p;
23             sum+=bag[i].v;
24         }
25         memset(dp,0,sizeof(dp));
26         dp[0]=1;
27         for(int i=0;i<n;i++){
28             for(int j=sum;j>=bag[i].v;j--){
29                 dp[j]=max(dp[j],dp[j-bag[i].v]*(1-bag[i].p));
30             }
31         }
32         for(int i=sum;i>=0;i--){
33             if(dp[i]>1-p){
34                 cout<<i<<endl;
35                 break;
36             }
37         }
38     }
39     return 0;
40 }
51 Nod 1085 背包问题
题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1085
在N件物品取出若干件放在容量为W的背包里,每件物品的体积为W1,W2……Wn(Wi为整数),与之相对应的价值为P1,P2……Pn(Pi为整数)。求背包能够容纳的最大价值。

Input
第1行,2个整数,N和W中间用空格隔开。N为物品的数量,W为背包的容量。(1 <= N <= 100,1 <= W <= 10000)
第2 - N + 1行,每行2个整数,Wi和Pi,分别是物品的体积和物品的价值。(1 <= Wi, Pi <= 10000)
Output
输出可以容纳的最大价值。
Input示例
3 6
2 5
3 8
4 9
Output示例
14

题解:01背包模板
 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <string.h>
 4 using namespace std;
 5 int dp[100005];
 6 int main()
 7 {
 8     int n,w,x,y;
 9     scanf("%d%d",&n,&w);
10     memset(dp,0,sizeof(dp));
11     for(int i=1;i<=n;i++){
12         scanf("%d%d",&x,&y);
13         for(int j=w;j>=x;j--){
14             dp[j]=max(dp[j],dp[j-x]+y);
15         }
16     }
17     cout<<dp[w]<<endl;
18     return 0;
19 }
View Code

51Nod  1086 背包问题 V2 

有N种物品,每种物品的数量为C1,C2......Cn。从中任选若干件放在容量为W的背包里,每种物品的体积为W1,W2......Wn(Wi为整数),与之相对应的价值为P1,P2......Pn(Pi为整数)。求背包能够容纳的最大价值。
 
Input
第1行,2个整数,N和W中间用空格隔开。N为物品的种类,W为背包的容量。(1 <= N <= 100,1 <= W <= 50000)
第2 - N + 1行,每行3个整数,Wi,Pi和Ci分别是物品体积、价值和数量。(1 <= Wi, Pi <= 10000, 1 <= Ci <= 200)
Output
输出可以容纳的最大价值。
Input示例
3 6
2 2 5
3 3 8
1 4 1
Output示例
9

题解:多重背包
 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <string.h>
 4 using namespace std;
 5 int dp[500005];
 6 int main()
 7 {
 8     int n,m,w,c,p,k,flag;
 9     scanf("%d%d",&n,&m);
10     memset(dp,0,sizeof(dp));
11     for(int i=1;i<=n;i++){
12         scanf("%d%d%d",&w,&p,&c);
13         for(k=1,flag=1; ;k*=2){
14             if(k*2>=c){
15                 k=c-k+1;
16                 flag=0;
17             }
18         for(int j=m;j >= k*w;j--){
19             dp[j]=max(dp[j],dp[j-k*w]+k*p);
20 
21         }
22         if(flag==0) break;
23         }
24     }
25     cout<<dp[m]<<endl;
26     return 0;
27 }

 



posted @ 2017-08-08 11:24  wydxry  阅读(425)  评论(0编辑  收藏  举报
Live2D