背包问题整理

来源:互联网 发布:mac磁盘在哪里 编辑:程序博客网 时间:2024/06/16 15:37

{引}.了解背包问题:

<讲解链接1>
http://dongxicheng.org/structure/knapsack-problems/

<讲解链接2>
http://www.cppblog.com/tanky-woo/archive/2010/07/31/121803.html


{一}.0/1背包:

<讲解链接>
http://blog.csdn.net/mu399/article/details/7722810


<板子题>

题目描述:
一个旅行者有一个最多能用 m 公斤的背包,现在有 n 件物品,它们的重量分别是 W1 ,W2 ,… , Wn ,它们的价值分别为 C1,C2 ,… ,Cn 。若每种物品只有一件求旅行者能获得最大总价值。

输入格式:
第 1 行:两个整数,M(背包容量,M≤200)和 N(物品数量,N≤30)。
第 2..N+1 行:每行二个整数 Wi,Ci,表示每个物品的重量和价值。

输出格式:
仅一行,一个数,表示最大总价值。

样例数据 1
输入:
10 4
2 1
3 3
4 5
7 9

输出:
12


代码(优化过后):

#include<bits/stdc++.h>using namespace std;int n,m;int w[505],v[505];int f[505];int main(){    memset(f,0,sizeof(f));    cin>>m>>n;    for(int i=1;i<=n;++i)        cin>>w[i]>>v[i];    for(int i=1;i<=n;++i)        for(int j=m;j>=w[i];--j)            f[j]=max(f[j],f[j-w[i]]+v[i]);    cout<<f[m]<<endl;    return 0;}

{二}.完全背包

<讲解链接>
http://blog.csdn.net/yumerina/article/details/55098880


<板子题>

题目描述:
设有 n 种物品,每种物品有一个重量及一个价值。但每种物品的数量是无限的,同时有一个背包,最大载重量为 M ,今从 n 种物品中选取若干件(同一种物品可以多次选取),使其重量的和小于等于 M ,而价值的和为最大。

输入格式:
第 1 行:两个整数,M(背包容量,M<=200)和 N(物品数量,N<=200)。
第 2..N+1 行:每行二个整数 Wi,Ci,表示每个物品的重量和价值。

输出格式:
仅一行,一个数,表示最大总价值。

样例数据 1
输入:
12 4
2 1
3 3
4 5
7 9

输出
15


代码:

#include<bits/stdc++.h>using namespace std;int n,m;int w[505],v[505];int f[505];int main(){    memset(f,0,sizeof(f));    cin>>m>>n;    for(int i=1;i<=n;++i)        cin>>w[i]>>v[i];    for(int i=1;i<=n;++i)        for(int j=w[i];j<=m;++j)            f[j]=max(f[j],f[j-w[i]]+v[i]);    cout<<f[m]<<endl;    return 0;}

{三}.二维背包

个人理解:类似一维的背包问题,只不过要开二维数组,多一个考虑条件,多一层for循环。

<讲解链接>
http://www.cnblogs.com/xiaofanke/archive/2012/08/22/2651290.html


例题:

HDU 2159 – Fate

题目描述:
最近xhd正在玩一款叫做FATE的游戏,为了得到极品装备,xhd在不停的杀怪做任务。久而久之xhd开始对杀怪产生的厌恶感,但又不得不通过杀怪来升完这最后一级。现在的问题是,xhd升掉最后一级还需n的经验值,xhd还留有m的忍耐度,每杀一个怪xhd会得到相应的经验,并减掉相应的忍耐度。当忍耐度降到0或者0以下时,xhd就不会玩这游戏。xhd还说了他最多只杀s只怪。请问他能升掉这最后一级吗?

输入格式:
输入数据有多组,对于每组数据第一行输入n,m,k,s(0 < n,m,k,s < 100)四个正整数。分别表示还需的经验值,保留的忍耐度,怪的种数和最多的杀怪数。接下来输入k行数据。每行数据输入两个正整数a,b(0 < a,b < 20);分别表示杀掉一只这种怪xhd会得到的经验值和会减掉的忍耐度。(每种怪都有无数个)

输出格式:
输出升完这级还能保留的最大忍耐度,如果无法升完这级输出-1。

样例数据 1
输入:
10 10 1 10
1 1
10 10 1 9
1 1
9 10 2 10
1 1
2 2

输出:
0
-1
1


代码:

#include<iostream>#include<algorithm>#include<cstdio>#include<cctype>#include<cstring>#include<queue>using namespace std;int n,m,k,s;int a[505],b[505];int f[505][505];inline void work(){    memset(f,0,sizeof(f));    int x,y,z;    for(x=1;x<=m;++x)    {           for(y=1;y<=k;++y)              for(z=1;z<=s;++z)            {                int cnt = 1;                while(cnt*b[y]<=x && cnt<=z)                {                    f[x][z]=max(f[x][z],f[x-cnt*b[y]][z-cnt]+cnt*a[y]);                    ++cnt;                }            }        if(f[x][s]>=n)            break;    }    if(x>m) cout<<"-1"<<endl;    else    cout<<m-x<<endl;}int main(){    while(cin>>n)    {        cin>>m>>k>>s;        for(int i=1;i<=k;++i)            cin>>a[i]>>b[i];        work();    }    return 0;}

{四}.多重背包

<讲解链接>
http://blog.csdn.net/chuck001002004/article/details/50340819


{五}.分组背包

<讲解链接>
http://www.cnblogs.com/ziyi–caolu/p/3223041.html


{结}.背包问题总结

<链接.经典背包九讲>
http://love-oriented.com/pack/


{At The End}

<推荐题目并链接>

1.hdu 2955 Robberies 01背包
http://acm.split.hdu.edu.cn/showproblem.php?pid=2955

2.hdu 1864 最大报销额 01背包
http://acm.split.hdu.edu.cn/showproblem.php?pid=1864

3.hdu 2602 Bone Collector 01背包
http://acm.split.hdu.edu.cn/showproblem.php?pid=2602

4.hdu 2844 Coins 多重背包
http://acm.split.hdu.edu.cn/showproblem.php?pid=2844

5.hdu 2159 FATE 二维背包/完全背包
http://acm.split.hdu.edu.cn/showproblem.php?pid=2159

6.hdu 1712 ACboy needs your help 分组背包
http://acm.split.hdu.edu.cn/showproblem.php?pid=1712