前些天在做动态规划的题,感觉动态规划博大精深,没有一种特定的模式,学起来很费劲。在这里就动态规划中的背包问题谈谈。
三种背包问题:0/1背包,完全背包,多重背包。
0/1背包:有n件物品和容量为v的背包,求解将哪些物品放入背包中可以使获得的价值最大。
f[i][v]表示将前i件物品恰好放入容量为v的背包可以获得的最大价值。
1.子问题:将前i件物品放入背包中,若第i件物品不放入背包中,则问题转化为求前i-1个物品放入容量为v的背包;若第i件物品放入背包中,则问题转化为求前i-1个物品放入容量为v-c[i]的背包。
2.转移方程:f[i][v] = max{f[i-1][v], f[i-1][v-c[i]]+w[i]},f[n][v]即为所求。
注意:初始化细节问题,若题目要求恰好装满背包,在初始化时除了f[0]=0,其余设为负无穷;若题目不要求非要装满背包,初始化f[0..v] = 0;
0/1背包代码:
int DP[14000];
int cost[3403],value[3403];
int main()
{
int i,v;
int n,m;
memset(DP,0,sizeof(DP));
scanf("%d %d",&n,&m);
for(i=1;i<=n;i++)
scanf("%d %d",&cost[i],&value[i]);
for(i=1;i<=n;i++)
{
for(v=m;v>=cost[i];v--)
{
if(DP[v-cost[i]]+value[i]>=DP[v])
DP[v]=DP[v-cost[i]]+value[i];
}
}
printf("%d\n",DP[m]);
return 0;
}
完全背包:有n种物品和容量为v的背包,每种物品可以无限选择,求解将哪些物品放入背包中可获得最大价值。
转化为0/1背包:将第i种物品拆分成费用为c*2^k,价值为w*2^k的若干物品,其中k满足c*2^k<V。这是二进制的思想,因为不管选择几件第i种物品,总可以表示成若干个2^k个物品。但我们有更优的算法,这个算法与0/1背包只有第二重循环的顺序不同。(至于为神马,弄得懂就好,不懂也可以跳过)
多重背包:有n种物品和容量为v的背包,第i种物品最多可有n件,求解问题同上。
转化为0/1背包:
将第i种物品分成若干件物品,其中每件物品有一个系数,这个物品的价值和费用是原来的费用和价值乘以这个系数。使这些系数分别为1、2、4、...、2^(k-1)、n-2^k+1,且k是满足n-2^k+1>0的最大整数。例如n=13,则可以分为1、2、4、6。这样就将第i中物品分成了log(n)件。
根据背包九讲,多重背包代码:
#include <iostream>
const int MAX = 100002;
int v; //背包的容量
int f[MAX]; //背包的最大容量为MAX. f[i][v]表示前i个物品恰放入容量为j的背包获得的最大值,可以优化为f[v]
void multiplePack(int value, int cost, int amount) //value表示价值,cost表示费用,amount表示物品个数
{
int i,j,k;
if(amount*cost >= v)
{
//完全背包
for(i = cost; i <= v; i++)
{
if(f[i] < f[i-cost] + value)
f[i] = f[i-cost] + value;
}
}
else
{
k = 1;
while(k < amount)
{
//0/1背包
for(i = v; i >= k*cost; i--)
{
if(f[i] < f[i-k*cost] + k*value)
f[i] = f[i-k*cost] + k*value;
}
amount -= k;
k = k*2;
}
for(i = v; i >= amount*cost; i--)
{
if(f[i] < f[i-amount*cost] + amount*value)
f[i] = f[i-amount*cost] + amount*value;
}
}
}
int main()
{
int n;
int i,j;
int num,value;
while(scanf("%d",&v) != EOF)
{
memset(f,0,sizeof(f));
scanf("%d",&n);
for(i = 1; i <= n; i++)
{
scanf("%d %d",&num,&value);
multiplePack(value,value,num);
}
printf("%d\n",f[v]);
}
return 0;
}
参见poj3624 1276
分享到:
相关推荐
背包问题是动态规划领域中一个非常经典的题目,其主要解决的问题是在给定的总重量限制下,如何选择物品,使得最终获得的物品价值最大化。 背包问题主要可以分为以下几种类型: 1. 01背包问题:这是最基本的背包...
对于0-1背包问题,动态规划的解决方案通常包括以下步骤: 1. 初始化:创建一个二维数组`dp`,其中`dp[i][j]`表示在前`i`件物品中选择总重量不超过`j`的物品所能得到的最大价值。初始化时,`dp[0][j] = 0`,因为没有...
在这个主题中,我们聚焦于一种经典的算法——回溯法,以及它在解决背包问题中的应用。回溯法是一种试探性的解决问题的方法,当遇到无法继续进行的情况时,会尝试撤销最近的选择,返回到一个更早的状态,寻找其他可能...
总结起来,这个C语言程序使用动态规划解决背包问题,通过创建和填充一个二维数组来存储子问题的解,从而找到最优解。这是对动态规划和背包问题的一个基础应用,对于初学者来说是一个很好的实践案例。在实际编程中,...
背包问题(Knapsack ...试用贪心算法和动态规划方法来解决0-1背包问题,采用所提供的数据集合. 作业需要提供实验报告,包括伪代码和运行代码,以及每个测试问题的运行时间、结果,如果无法在有限时间得到答案则为N.A.
利用遗传算法求解特定组合优化背包问题——背包问题
在动态规划领域,背包问题是一个非常重要的模型,因为它能直观地展示动态规划的思想。 1. **动态规划**是一种通过将大问题分解为小问题并存储子问题的解来避免重复计算的算法设计策略。在背包问题中,动态规划可以...
### 贪心算法在背包问题中的应用 #### 一、引言 背包问题是一种经典的组合优化问题,在实际生活中有着广泛的应用场景,如资源分配、货物装载等。它主要研究如何从一组物品中选择部分物品放入背包中,使得背包内的...
动态规划通常涉及到的问题类型包括但不限于最短路径、背包问题、最长公共子序列、矩阵链乘法等。下面我们将逐一解析这些经典问题及其动态规划解决方案。 1. 最短路径问题:如著名的Dijkstra算法和Floyd-Warshall...
数据结构中的背包问题是一个经典的优化问题,涉及到动态规划和回溯法等算法设计。这个问题的目标是在给定的容量限制下,选择物品以达到最大的价值或体积。在这个特定的例子中,我们关注的是找到所有能恰好装满背包的...
### 0-1背包问题与动态规划 #### 一、问题背景及定义 在计算机科学领域,0-1背包问题是一种经典的组合优化问题。这个问题可以这样描述:假设有一个背包,其承重能力为C(即最大容量),背包里可以装入n种物品中的...
《算法分析与软件设计》课程设计报告展示了如何利用贪心法和回溯法解决01背包问题。01背包问题是一个经典的组合优化问题,旨在在不超过背包容量限制的前提下,选择物品以最大化总价值。在这个问题中,物品是不可分割...
这个是动态规划之跳跃点0-1背包问题,如果只是想要动态规划0-1背包问题求解代码,请到主页查看。18级学姐自主完成的算法作业,呕心沥血,基于四舍五入等于0基础的python实现,如果在语言规范上存在不足,那就。就憋...
### 01背包问题动态规划详解及其学习意义 #### 一、01背包问题概述 01背包问题作为计算机科学领域中的一个经典问题,属于组合优化问题的一种。该问题的基本形式如下:假设我们有一个背包,这个背包的最大承重为W...
动态规划是解决0-1背包问题的关键方法。动态规划是一种通过将复杂问题分解为更小的子问题来求解的方法,其核心思想是避免重复计算,通过构建表格存储已解决的子问题结果,以达到高效求解的目的。 在这个程序`zero_...
### 动态规划经典——背包九讲 #### 1. 01背包问题 **1.1 题目** 给定N件物品和一个容量为V的背包,每件物品都有自己的重量c[i]和价值w[i]。求解哪些物品能够放入背包内使得总价值最大。 **1.2 基本思路** 01...
标签“knapsack_dynamic”直指问题的核心——背包问题,这通常是一个优化问题,目标是在不超过给定容量的限制下,选取一组物品,使得物品的总价值最大。动态规划法是解决此类问题的标准方法。 “动态规划法”是解决...
本实验旨在通过理论分析与实践操作相结合的方式,帮助学生掌握0-1背包问题的两种常用求解方法——动态规划法和回溯法,并深入理解这两种方法的工作原理、优缺点以及适用场景。 #### 二、算法介绍与分析 ##### 1. ...
动态规划(DP)——背包问题算法详解[背包九讲]