关于几个背包问题(C语言)

个人新学的几个背包问题,做下记录总结。(参考博客:http://blog.csdn.net/mu399/article/details/7722810  以及 http://blog.csdn.net/u013174702/article/details/45741395)

(1)01背包:

01背包的状态转换方程 f[i,j] = Max{ f[i-1,j-Wi]+Pi,  f[i-1,j] }

f[i,j]表示在前i件物品中选择若干件放在承重为 j 的背包中,可以取得的最大价值。

Pi表示第i件物品的价值。该方程说白了就是比较放第i个和不放第i个物品两种决策,哪种决策价值大就选择哪种 。

我们举个例子来理解下:

假设f[i-1,j]表示我有一个承重为8的背包,当只有物品b,c,d,e四件可选时,这个背包能装入的最大价值9,现在有个重量Wi为2 价值为Pi为6
的物品a,考虑是否放入承重为8的背包使其价值最大,f[i-1,j-Wi]代表一个承重为6的背包的最大价值(等于当前背包承重8减去物品a的重量2),
当只有物品b,c,d,e四件可选时,这个背包能装入的最大价值为8
由于f[i-1][v-Wi]+w[i]= 9 + 6 = 15 大于f[i][v] = 8,所以物品a应该放入承重为8的背包。

总的来说:

方程之中,现在需要放置的是第i件物品,这件物品的重量是Wi,价值是Pi,因此f[i-1,j]代表的就是不将这件物品放入背包,而f[i-1],j-Wi]]+Pi则是代表将第i件放入背包之后的总价值,比较两者的价值,得出最大的价值存入现在的背包之中。

附上南阳oj上的一个题(49题):

开心的小明

时间限制:1000 ms  |  内存限制:65535 KB

难度:4

描述
小明今天很开心,家里购置的新房就要领钥匙了,新房里有一间他自己专用的很宽敞的房间。更让他高兴的是,妈妈昨天对他说:“你的房间需要购买哪些物品,怎么布置,你说了算,只要不超过N 元钱就行”。今天一早小明就开始做预算,但是他想买的东西太多了,肯定会超过妈妈限定的N 元。于是,他把每件物品规定了一个重要度,分为5 等:用整数1~5 表示,第5 等最重要。他还从因特网上查到了每件物品的价格(都是整数元)。他希望在不超过N 元(可以等于N 元)的前提下,使每件物品的价格与重要度的乘积的总和最大。设第j 件物品的价格为v[j],重要度为w[j],共选中了k 件物品,编号依次为j1...jk,则所求的总和为:v[j1]*w[j1]+..+v[jk]*w[jk]请你帮助金明设计一个满足要求的购物单.
输入
第一行输入一个整数N(0<N<=101)表示测试数据组数

每组测试数据输入的第1 行,为两个正整数,用一个空格隔开:

N m

(其中N(<30000)表示总钱数,m(<25)为希望购买物品的个数。)

从第2 行到第m+1 行,第j 行给出了编号为j-1

的物品的基本数据,每行有2 个非负整数

v p

(其中v 表示该物品的价格(v≤10000),p 表示该物品的重要度(1~5))

输出
每组测试数据输出只有一个正整数,为不超过总钱数的物品的价格与重要度乘积的总和的

最大值(<100000000)

样例输入
1
1000 5
800 2
400 5
300 5
400 3
200 2
样例输出
3900解决代码://01背包问题,开心的小明 #include<stdio.h>#include<string.h>#include<algorithm>  using namespace std; int dp[30001];//dp[i]表示质量为i时的最大价值struct bag{ int v; int p; }a[26];int main(){int n;scanf("%d",&n);  while(n--){  int N,m,i,j;  scanf("%d%d",&N,&m);   for(i=1;i<=m;i++)  scanf("%d%d",&a[i].v,&a[i].p);memset(dp,0,sizeof(dp));  for(i=1;i<=m;i++){    for(j=N;j>=a[i].v;j--){    dp[j]=max(dp[j-a[i].v]+a[i].v*a[i].p,dp[j]);        }//确定要不要买价格为j的第i件物品,总是使dp的值最大    }  printf("%d\n",dp[N]);   }    }(2)又见01背包:

又见01背包(通过南阳Oj一个例题来体现)

时间限制:1000 ms  |  内存限制:65535 KB

难度:3

描述

    有n个重量和价值分别为wi 和 vi 的 物品,从这些物品中选择总重量不超过 W

的物品,求所有挑选方案中物品价值总和的最大值。

  1 <= n <=100

  1 <= wi <= 10^7

  1 <= vi <= 100

  1 <= W <= 10^9

输入
多组测试数据。

每组测试数据第一行输入,n 和 W ,接下来有n行,每行输入两个数,代表第i个物品的wi 和 vi。

输出
满足题意的最大价值,每组测试数据占一行。
样例输入
4 5
2 3
1 2
3 4
2 2
样例输出
7这题起初看以为就是普通的背包问题,仔细一看如果用dp[W]来表示质量为wi时的最大价值,因为W的范围太大开不了那么大的数组,所以解决方法就是把价值和重量翻转,改用较小的价值来开数组,那么最后求的就是指定价值下的最小重量。附上代码:#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;struct bag{  int w;  int v;    }a[101];int dp[100000];int main(){int n,W; while(scanf("%d%d",&n,&W)!=EOF){int i,j,sum=0;

 for(i=0;i<n;i++){ scanf("%d%d",&a[i].w,&a[i].v);     sum+=a[i].v; } for(i=0;i<=sum;i++) dp[i]=1e9; dp[0]=0; for(i=0;i<n;i++){   for(j=sum;j>=a[i].v;j--){       dp[j]=min(dp[j-a[i].v]+a[i].w,dp[j]);//dp[]代表指定价值下的最小重量,j为指定价值      }     } for(i=sum;i>=0;i--){//按顺序从大到小输出dp的值,即重量对应的价值  if(dp[i]<=W){ printf("%d\n",i); break; }}}} (3)完全背包:

完全背包(南阳oj311题)

时间限制:3000 ms  |  内存限制:65535 KB

难度:4

描述

直接说题意,完全背包定义有N种物品和一个容量为V的背包,每种物品都有无限件可用。第i种物品的体积是c,价值是w。求解将哪些物品装入背包可使这些物品的体积总和不超过背包容量,且价值总和最大。本题要求是背包恰好装满背包时,求出最大价值总和是多少。如果不能恰好装满背包,输出NO

输入
第一行: N 表示有多少组测试数据(N<7)。

接下来每组测试数据的第一行有两个整数M,V。 M表示物品种类的数目,V表示背包的总容量。(0<M<=2000,0<V<=50000)

接下来的M行每行有两个整数c,w分别表示每种物品的重量和价值(0<c<100000,0<w<100000)

输出
对应每组测试数据输出结果(如果能恰好装满背包,输出装满背包时背包内物品的最大价值总和。 如果不能恰好装满背包,输出NO)
样例输入
2
1 5
2 2
2 5
2 2
5 1

代码:#include<stdio.h>#include<algorithm>using namespace std;int dp[50005],c[2001],w[2001];    int main(){int N,M,V,i,j;scanf("%d",&N);while(N--){ scanf("%d%d",&M,&V);for(i=1;i<=V;i++)dp[i]=-1000000;dp[0]=0;for(i=0;i<M;i++)scanf("%d%d",&c[i],&w[i]);  for(i=0;i<M;i++){      for(j=c[i];j<=V;j++){      dp[j]=max(dp[j-c[i]]+w[i],dp[j]);      }      }  if(dp[V]<0) printf("NO\n"); else printf("%d\n",dp[V]); }    }

解题思路:
0-1背包的状态转移方程是
for i = 1 to N
for v = V to Ci
F [v] = max{F [v],F [v ? Ci] + Wi}完全背包就是不限制物品使用个数,可以无限使用,也就是可以重复放置一个物体
转移方程
for i = 1 to N
for v = Ci to V
F [v] = max(F [v], F [v ? Ci] + Wi)你会发现,这个伪代码与01背包问题的伪代码只有v的循环次序不同而已。
为什么这个算法就可行呢?首先想想为什么01背包中要按照v递减的次序来
循环。让v递减是为了保证第i次循环中的状态F [i, v]是由状态F [i ? 1, v ? Ci]递
推而来。换句话说,这正是为了保证每件物品只选一次,因为质量在减少不可能再能加入一个和原来质量一样大的物品,而现在完全背包的特点恰是每种物品可选无限件,所以采用“质量增加”的循环,因此后面可能会继续加入和原来质量一样的物品。

时间: 2024-08-03 16:25:27

关于几个背包问题(C语言)的相关文章

背包问题-C语言实现

转自:http://blog.csdn.net/tjyyyangyi/article/details/7929665 0-1背包问题 参考: http://blog.csdn.net/liwenjia1981/article/details/5725579 http://blog.csdn.net/dapengbusi/article/details/7463968 动态规划解法 借个图 助于理解 从背包容量为0开始,1号物品先试,0,1,2,的容量都不能放.所以置0,背包容量为3则里面放4.这

c语言-完全背包问题

完全背包问题 问题:有N种物品和一个容量为V的背包,每种物品都有无限件可用.第i种物品的费用是c[i],价值是w[i].求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大. 分析: 这个算法使用一维数组,先看伪代码: for i=1..N    for v=0..V        f[v]=max{f[v],f[v-cost]+weight} 这个伪代码与P01的伪代码只有v的循环次序不同而已. 为什么这样一改就可行呢?首先想想为什么P01中要按照v=V..0的逆序来循环

C语言-多重背包问题

多重背包问题 问题:有N种物品和一个容量为V的背包.第i种物品最多有n[i]件可用,每件费用是c[i],价值是w[i].求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大. 分析: 这题目和完全背包问题很类似.基本的方程只需将完全背包问题的方程略微一改即可,因为对于第i种物品有n[i]+1种策略:取0件,取1件--取n[i]件.令f[i][v]表示前i种物品恰放入一个容量为v的背包的最大权值,则有状态转移方程: f[i][v]=max{f[i-1][v-k*c[i]]+k

c语言-01背包问题

01背包问题 问题:有N件物品和一个容量为V的背包.第i件物品的费用是c[i],价值是w[i].求解将哪些物品装入背包可使价值总和最大. 分析: 这是最基础的背包问题,特点是:每种物品仅有一件,可以选择放或不放. 用子问题定义状态:即f[i][v]表示前i件物品恰放入一个容量为v的背包可以获得的最大价值.则其状态转移方程便是: f[i][v]=max{f[i-1][v],f[i-1][v-c[i]]+w[i]} 这个方程非常重要,基本上所有跟背包相关的问题的方程都是由它衍生出来的.所以有必要将它

C语言-二维背包问题

二维费用背包问题 问题: 二维费用的背包问题是指:对于每件物品,具有两种不同的费用:选择这件物品必须同时付出这两种代价:对于每种代价都有 一个可付出的最大值(背包容量).问怎样选择物品可以得到最大的价值.设这两种代价分别为代价1和代价2,第i件物品所需的两种代价分别为a[i]和 b[i].两种代价可付出的最大值(两种背包容量)分别为V和U.物品的价值为w[i]. 分析: 费用加了一维,只需状态也加一维即可.设f[i][v][u]表示前i件物品付出两种代价分别为v和u时可获得的最大价值.状态转移方

从01背包问题理解动态规划---初体验

01背包问题具体例子:假设现有容量10kg的背包,另外有3个物品,分别为a1,a2,a3.物品a1重量为3kg,价值为4:物品a2重量为4kg,价值为5:物品a3重量为5kg,价值为6.将哪些物品放入背包可使得背包中的总价值最大? 这个问题有两种解法,动态规划和贪婪算法.本文仅涉及动态规划. 先不套用动态规划的具体定义,试着想,碰见这种题目,怎么解决? 首先想到的,一般是穷举法,一个一个地试,对于数目小的例子适用,如果容量增大,物品增多,这种方法就无用武之地了. 其次,可以先把价值最大的物体放入

《算法导论》读书笔记之第16章 0-1背包问题—动态规划求解

原文:http://www.cnblogs.com/Anker/archive/2013/05/04/3059070.html 1.前言 前段时间忙着搞毕业论文,看书效率不高,导致博客一个多月没有更新了.前段时间真是有些堕落啊,混日子的感觉,很少不爽.今天开始继续看算法导论.今天继续学习动态规划和贪心算法.首先简单的介绍一下动态规划与贪心算法的各自特点及其区别.然后针对0-1背包问题进行讨论.最后给出一个简单的测试例子,联系动态规划实现0-1背包问题. 2.动态规划与贪心算法 关于动态规划的总结

C语言-让生活更美好

1.智能车 1)避障车 2)平衡车 3)WIFI视频车 2.萝莉语音温度播报 3.万年不变的万年历 4.采矿致富车--------------电赛作品--金属探测车 5.基于物联网的家庭安防系统-----九宫格解锁(隔空解锁) 6.基于心理治疗的儿童电子琴 7.蓝牙防丢器 8.操作系统 9.喂水器:(小狗走近就会滴水) 10.喂食器:(小狗走近就会落食) 举几个用c开发的程序例子. QQ notepad(记事本).notepad++.notepad2 pidgin(全平台的聊天软件) apach

背包问题问法的变化(背包九讲)

前言: 以上涉及的各种背包问题都是要求在背包容量(费用)的限制下求可以取到的最大价值,但背包问题还有很多种灵活的问法,在这里值得提一下.但是我认为,只要深入理解了求背包问题最大价值的方法,即使问法变化了,也是不难想出算法的.例如,求解最多可以放多少件物品或者最多可以装满多少背包的空间.这都可以根据具体问题利用前面的方程求出所有状态的值(f数组)之后得到.还有,如果要求的是"总价值最小""总件数最小",只需简单的将上面的状态转移方程中的max改成min即可.下面说一些