背包问题

洛谷背包问题:P2851 [USACO06DEC]最少的硬币The Fewest Coins(完全背包+多重背包+抽屉原理)

坚强是说给别人听的谎言 提交于 2019-11-28 07:19:13
题目描述 Farmer John has gone to town to buy some farm supplies. Being a very efficient man, he always pays for his goods in such a way that the smallest number of coins changes hands, i.e., the number of coins he uses to pay plus the number of coins he receives in change is minimized. Help him to determine what this minimum number is. FJ wants to buy T (1 ≤ T ≤ 10,000) cents of supplies. The currency system has N (1 ≤ N ≤ 100) different coins, with values V1, V2, ..., VN (1 ≤ Vi ≤ 120). Farmer John is carrying C1 coins of value V1, C2 coins of value V2, ...., and CN coins of value VN (0 ≤ Ci ≤ 10

多叉树的背包问题

房东的猫 提交于 2019-11-28 05:46:16
明天开学 问题模型一般是: 给定n个物品,有一个容积为V的背包,每个物品依赖一个物品,选择一个必须选择所依赖的物品,依赖关系构成一棵树,每个物品有体积,价值,最大化价值; 这种模型称作树形有依赖背包问题; 常见方法大概有三种: 1.多叉树转化为二叉树: 将一个节点的多个儿子中选择最左的儿子保留下来,剩下的儿子放到左儿子的右子树里; 来张图片: 状态转移即为: 设dp[i][j]表示在以i为根的子树中,用大小为j的包能取得的最大价值, dp[i][j]=max(dp[left[i]][j-w[i]]+v[i],dp[right[i]][j]); left[i]是i在原树中的第一个儿子,right[i]是i在原树中的下一个兄弟。 第二种方法: dfs序表示法: 我们对于每一个节点求出他在原树中的dfs序dfn值,然后记录他的子数大小size; 那么对于一个节点x:x的第一个儿子y 有 dfn[y]=dfn[x]+1; 对于x的第二个儿子z, dfn[z]=dfn[x]+size[y]+1 ; 对于x的一个兄弟k,有d fn[k]=dfc[x]+size[x]+1 ; 一个dfs序为i的节点u,同样设dp[i][j]表示在以u为根的子树中,用大小为j的包能取得的最大价值, dp[i][j]+w [i]->dp[i+1][j-v[i]] dp[i][j]->dp[i+size[i]+1]

面试现场:秒解0-1背包问题

余生长醉 提交于 2019-11-28 05:45:44
概述 背包问题 (Knapsack problem)是一种组合优化的 NP完全 问题。问题可以描述为:给定一组物品,每种物品都有自己的重量和价格,在限定的总重量内,我们如何选择,才能使得物品的总价格最高。问题的名称来源于如何选择最合适的物品放置于给定背包中。 定义 我们有 n 种物品,物品 j 的重量为 wj ,价格为 pj 。 我们假定所有物品的重量和价格都是非负的。背包所能承受的最大重量为 W 。 如果限定每种物品只能选择0个或1个,则问题称为 0-1背包问题 。 如果限定物品 j 最多只能选择 bj 个,则问题称为 有界背包问题 。 如果不限定每种物品的数量,则问题称为 无界背包问题 。 思路 举例,令物品数量N=5,背包所能承受的最大重量为W=10,物品与价格的对应关系如下表左三列所示。 name weight value 1 2 3 4 5 6 7 8 9 10 a 2 6 0 6 6 6 6 6 6 6 6 6 b 2 3 0 6 6 9 9 9 9 9 9 9 c 6 5 0 6 6 9 9 9 9 11 11 14 d 5 4 0 6 6 9 9 9 10 11 13 14 e 4 6 0 6 6 9 9 12 12 15 15 15 当放入物品a时,在背包所能承受的重量内,计算背包拥有的物品总价格,并进行标记,如表格第一行所示,当背包所能承受的重量大于等于2时

背包问题后续3

淺唱寂寞╮ 提交于 2019-11-28 03:31:35
问题描述: 使用一个货币系统{1,2,5,10,...}产生18 单位面值的一些可能的方法是:18x1, 9x2, 8x2+2x1,3x5+2+1,等等其它。 写一个程序来计算有多少种方法用给定的货币系统来构造一定数量的面值。保证总数将会适合long long (C/C++) 和Int64 (Free Pascal)。 例如:使用{1,2,5}三种货币各无限,来组合出10元,一共有10种方式。 怎么思考? 用dp[i][j] 来表示使用前i种货币组合成j元的方式有多少种。 对于第i种货币,可以不选,问题转变为 使用前i-1 种货币组合j元有多少种。 dp[ i-1 ][ j ] 如果选的话,可以选1个、2个、...j/w[i]个,然后用剩下的i-1种组合。   sum{ dp[ i-1 ][ j - k*w[i] ] } k = 1,2,3,...j/w[i]。 综合上面两种方式, dp[i][j] = sum { dp[ i-1 ][ j - k*w[i] ] } k = 0,1,2,... j/w[i] 笨方法: dp[0][0] = 1; for(i = 1;i <= n;i++) { dp[i][0] = 1; for( j = 1 ; j<= sum; j++)//for( j = money[i-1] ; j<= sum; j++) { for(k = 0;k <= j

背包问题后续2

爷,独闯天下 提交于 2019-11-28 03:31:22
问题描述: 给出N种物品,每个物品无限件可选,对应的体积为w[i],这些物品可以使多大的背包完全装满? V <= 1000 直接在上一篇的基础上修改: 第i次循环后,dp[j]表示容量为j的背包可以被前i种物品装满。 递推关系: dp[j] == true => dp[j + w[i] ]= true j = 0...V 比如,j为0时,dp[ w[0] ] = true。j增大到w[0]时,dp[ w[0]*2 ]= true。j增大到2*w[0] ,dp[3*w[0]] = true。这是符合事实的。 第i轮循环开始之前,只要dp[j]=true,那么用前i种物品能组合到j,那么在这个基础上加上w[i],就能取到j+w[i]。 判断一个体积 V能否用前i种物品取到,可以先取一个物品i,再判断j-w[i]能否用剩下的i种物品填满。 也可以不取物品i,判断只用剩下的前i-1种物品能否填满j。 代码如下: int main() { int a[5] = { 8,3,12,9,7 }; int n = 5; int i,j,sum = 100; int dp[101] = {0}; dp[0] = 1; for(i = 0;i < n; i++) { for(j=0;j<=sum - a[i];j++) { dp[ j + a[i] ] |= dp[j]; } } return 0;

背包问题后续

梦想与她 提交于 2019-11-28 03:31:10
问题描述: 给出N个物品,每个物品的体积为w[i],这些物品可以使多大的背包完全装满? 分析: 用dp[v]表示容量为i的背包可以被装满。 0 <= v <= sum(w[i]) 在循环开始前,初始化dp[0] = true,dp[i] = false (i>0)。 第一次循环,表示只有一件物品可选,那么下标为w[0]的背包被置为true。 第二次循环,表示前两件物品可选。那么在所有置为true的下标基础上,加上一个w[1],依然为true。 dp[ j ] == true => dp[ j + w[i] ] = true 但是如果求解时,j从小到大求的话,就会出现问题。 比如 j = 0时, dp[ w[0] ]被置为true。j不断增大,当j = w[0]时,dp[ w[0] + w[0] ]也被置为true。 实际上,物品0只有一件,这样的情况是取不到的。 怎样避免?自然是用逆序求值了。 dp[ j ] = true 仅当 dp[ j - w[i] ] == true。 上代码: int main() { int a[6] = { 8,3,12,7,9,7 }; int n = 6; int i,j,sum = 46; int dp[47] = {0}; dp[0] = 1; for(i = 0;i < n; i++) { for(j=sum;j>=a[i];j--) {

背包问题 - 分支界限

耗尽温柔 提交于 2019-11-28 02:56:53
import java.util.*;public class Main{ public static final int ASD = 1000000007; public static void main(String[] args){ Scanner sc = new Scanner(System.in); int k=sc.nextInt(); int a=sc.nextInt(); int x=sc.nextInt(); int b=sc.nextInt(); int y=sc.nextInt(); int sum = 0; //k=17;a=5;x=79;b=4;y=66; //k=205;a=1;x=92;b=4;y=92; //3615040 sc.close(); int[] n = new int[x + y]; int[] e = new int[x + y]; for(int i = 0; i < n.length; i++){ if(i < x){ e[i] = a; } else{ e[i] = b; } n[i] = 0; } sum = dp(n, e, k, 0, -1); System.out.println(sum); } public static int dp(int[] n, int[] e, int k, int sum, int yn)

8.18 二讲背包问题之完全背包

烂漫一生 提交于 2019-11-27 17:01:34
  今天为大家讲解完全背包问题。   完全背包和01背包的区别便在于完全背包可以无限选取商品,而01背包只可以选取一个,从一维数组的角度来想,01背包从后往前枚举(m到w[i])可以保证每次j空间时只选取该商品选取了一次,避免了重复;而完全背包从前往后枚举(w[i]到m)会把小于m的2*w[i],3*w[i]...k*w[i]都加进来. 为大家放一道例题 题目描述 设有n种物品,每种物品有一个重量及一个价值。但每种物品的数量是无限的,同时有一个背包,最大载重量为M,今从n种物品中选取若干件(同一种物品可以多次选取),使其重量的和小于等于M,而价值的和为最大。 输入 第一行:两个整数,M(背包容量,M<=200)和N(物品数量,N<=30); 第2..N+1行:每行二个整数Wi,Ci,表示每个物品的重量和价值。 输出 仅一行,一个数,表示最大总价值。 样例输入 10 4 2 1 3 3 4 5 7 9 样例输出 max=12题解代码: #include<iostream> using namespace std; int m,n,dp[205],w[35],c[35]; int main(){ scanf("%d%d",&m,&n); for(int i=1;i<=n;i++){ scanf("%d%d",&w[i],&c[i]); } for(int i=1;i<=n;i++){

8.18 动态规划——背包问题之01背包

拥有回忆 提交于 2019-11-27 17:00:25
   今天为大家讲解一道动态规划的经典问题——背包问题之01背包,稍有难度的优化多重背包留到下一篇为大家讲解。 //为大家放一道模板题 题目描述 一个旅行者有一个最多能用m公斤的背包,现在有n件物品,它们的重量分别是W1,W2,...,Wn,它们的价值分别为C1,C2,...,Cn.若每种物品只有一件求旅行者能获得最大总价值。 输入 w第一行:两个整数,M(背包容量,M<=200)和N(物品数量,N<=30); w 第2..N+1行:每行二个整数Wi,Ci,表示每个物品的重量和价值。 输出 仅一行,一个数,表示最大总价值。 样例输入 10 4 2 1 3 3 4 5 7 9 样例输出 12 题解代码: #include<iostream> #include<string> using namespace std; int m,n,w[32],c[32],dp[32][305]; //int dp[305]; int main(){ //01背包 scanf("%d%d",&m,&n); for(int i=1;i<=n;i++){ scanf("%d%d",&w[i],&c[i]); } //普通二维数组做法 for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ if(j>=w[i]){ dp[i][j]=max(dp[i-1][j],dp[i

背包型动态规划

岁酱吖の 提交于 2019-11-27 16:30:00
背包问题也是动态规划中一个很经典的问题 其问题主要框架为:有一个体积为V的背包(花费上限),有n件物品,第i件物品的体积为v[i],价值为w[i],问怎么放的最大价值。 当然,不同的题会对物品有不一样的限制,比如对物品数量的限制,对物品关系的限制,因此就有了不同种类的背包问题。 一,01背包 问题:有一个体积为V的背包,有n件物品,第i件物品的体积为v[i],价值为w[i],每件物品至多选择一次,问在不超过背包体积的前提下能获得的最大价值。 这是背包型动态规划的基础,有些背包型动态规划可以转化为01背包,从而起到优化的效果。 特点是对于第i件物品,我们只有两种选择,第一种,将这件物品放入背包,第二种,不放这种物品,显然,我们想要在当前体积限制下获得最大的价值,如果放入这件物品 会使总的价值增大,我们就放入这件物品,否则不放。 状态转移方程 dp[i][v]=max(dp[i-1][v],dp[i-1][v-w[i]+c[i]]); 1 for(int i=1;i<=n;i++) 2 for(int v=1;v<=vmax,v++) 3 { 4 if(w[i]>v) dp[i][v]=dp[i-1][v]; 5 else dp[i][v]=max(dp[i-1][v],dp[i-1][v-w[i]]+c[i]); 6 } 我们可以通过数组的重复利用优化掉一维