背包专题(持续更新)
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 }
HDU 2602 Bone Collecter
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2602
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 }
HDU 2546 饭卡
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2546
某天,食堂中有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
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
第1行,2个整数,N和W中间用空格隔开。N为物品的数量,W为背包的容量。(1 <= N <= 100,1 <= W <= 10000) 第2 - N + 1行,每行2个整数,Wi和Pi,分别是物品的体积和物品的价值。(1 <= Wi, Pi <= 10000)
输出可以容纳的最大价值。
3 6 2 5 3 8 4 9
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 }
51Nod 1086 背包问题 V2
第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)
输出可以容纳的最大价值。
3 6 2 2 5 3 3 8 1 4 1
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 }