背包问题

在n个物品中挑选若干物品装入背包,最多能装多满?假设背包的大小为m,每个物品的大小为A[i]

样例

如果有4个物品[2, 3, 5, 7]

如果背包的大小为,可以选择[2, 3, 5]装入背包,最多可以装满的空间。

如果背包的大小为,可以选择[2, 3, 7]装入背包,最多可以装满的空间。

函数需要返回最多能装满的空间大小。

解题

动态规划

这是最基础的背包问题,特点是:每种物品仅有一件,可以选择放或不放。

用子问题定义状态:即f[i][j]前i个物品放入大小为j的空间里能够占用的最大体积。

则其状态转移方程便是:

f[i][j]=max{f[i-1][j],f[i-1][j-A[i]]+A[i]}

不放第i个物品:f[i-1][j]

放第i个物品:那么问题就转化为“前i-1件物品放入剩下的容量为j-A[i]的背包中”,此时能获得的最大体积就是f[i-1][j-A[i]]再加上通过放入第i件物品获得的体积A[i]

注意上面的状态转移方程i的下标是从1开始的,下面程序是从0开始的,要适当调整

public class Solution {
/**
* @param m: An integer m denotes the size of a backpack
* @param A: Given n items with size A[i]
* @return: The maximum size
*/
public int backPack(int m, int[] A) {
// write your code here
int[][] P = new int[A.length+1][m+1];
for(int i = 1;i<= A.length; i++){
for(int j = m;j>=0;j--){
if(j>=A[i-1]){
P[i][j] = P[i-1][j-A[i-1]] + A[i-1];
}
P[i][j] = Math.max(P[i][j],P[i-1][j]);
}
}
return P[A.length][m];
}
}

或者对0的时候单独考虑

public class Solution {
/**
* @param m: An integer m denotes the size of a backpack
* @param A: Given n items with size A[i]
* @return: The maximum size
*/
public int backPack(int m, int[] A) {
// write your code here
int[][] P = new int[A.length][m+1];
for(int i = 0;i< A.length; i++){
for(int j = m;j>=0;j--){
if(i==0){ // 第0个物品可以放入空间为j的背包中,直接放入
if(j>=A[i])
P[i][j] = P[i][j-A[i]] + A[i];
}else{
if(j>=A[i]){
P[i][j] = P[i-1][j-A[i]] + A[i];
}
P[i][j] = Math.max(P[i][j],P[i-1][j]);
} }
}
return P[A.length-1][m];
}
}

上面的时间空间复杂度都是O(MN)

状态转移方程式:

f[i][j] = Max(f[i-1][j],f[i-1][j-A[i]]+A[i])

f[i][j]表示对前i个物品,j的空间所能够取得的最大价值

实际上,我们需要求的是对所有的n个商品在m的空间中能够放入的最大价值

可以修改定义一个一维矩阵,长度就是m的空间的价值

f[j] = Max(f[j],f[j-A[i]]+A[i]) 这里就相当于对上面的矩阵进行了压缩

public class Solution {
/**
* @param m: An integer m denotes the size of a backpack
* @param A: Given n items with size A[i]
* @return: The maximum size
*/
public int backPack(int m, int[] A) {
// write your code here
int[] P = new int[m+1];
for(int i=0;i<A.length;i++){
for(int j=m;j>=0;j--){
if(j>=A[i])
P[j] = Math.max(P[j],P[j-A[i]] + A[i]);
}
}
return P[m];
}
}

参考:http://love-oriented.com/pack/P01.html

可以输出零钱的具体方案

package org.oj.dp;

import java.util.ArrayList;
import java.util.Arrays; public class 换零钱问题 {
static ArrayList<ArrayList<String>> lists;
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] A = {1,2,5,10,20,50}; lists = new ArrayList<ArrayList<String>>(11);
ArrayList<String> l1 = new ArrayList<String>();
l1.add("");
lists.add(l1);
for(int i=0;i<11;i++){
lists.add(new ArrayList<String>(10));
}
changeMoney(A,10);
System.out.println(lists);
}
/**
* 根据上一个零钱方案,更新当前零钱方案
* @param A
* @param money
*/
private static void changeMoney(int[]A,int money){
int[] dp = new int[money+1];
dp[0] = 1;
for(int i=0;i<A.length;i++){
for(int j=A[i];j<=money;j++){
dp[j] +=dp[j-A[i]];
// 记录零钱方案
for(int k=0;k<lists.get(j-A[i]).size();k++){
lists.get(j).add(lists.get(j-A[i]).get(k)+" "+A[i]);
}
}
}
System.out.println(Arrays.toString(dp));
}
/**
* DFS实现
* @param m
* @param A
* @param start
* @param result
* @param str
*/
private static void DFS(int m,int[]A,int start,ArrayList<String>result,String str){
if(m == 0){
result.add(str);
return;
}
if(A[start]> m){
return;
}
for(int i = start;i<A.length;i++){
DFS(m - A[i],A,i,result,str+ " "+A[i]);
}
} }

lintcode:背包问题的更多相关文章

  1. lintcode:背包问题II

    背包问题II 给出n个物品的体积A[i]和其价值V[i],将他们装入一个大小为m的背包,最多能装入的总价值有多大? 注意事项 A[i], V[i], n, m均为整数.你不能将物品进行切分.你所挑选的 ...

  2. 背包问题2 (lintcode)

    这里: for(int j = 1;j <= m;j++) result[0][j] = 0x80000000; 不能从0开始,result[0][0]是可以取到的,是0.其他情况取不到才用最小 ...

  3. 92.背包问题(lintcode)

    注意j-A[i-1]必须大于等于0,只大于0会报错 class Solution { public: /** * @param m: An integer m denotes the size of ...

  4. leetcode & lintcode for bug-free

    刷题备忘录,for bug-free leetcode 396. Rotate Function 题意: Given an array of integers A and let n to be it ...

  5. leetcode & lintcode 题解

    刷题备忘录,for bug-free 招行面试题--求无序数组最长连续序列的长度,这里连续指的是值连续--间隔为1,并不是数值的位置连续 问题: 给出一个未排序的整数数组,找出最长的连续元素序列的长度 ...

  6. lintcode 题目记录3

    Expression Expand  Word Break II Partition Equal Subset Sum  Expression Expand  字符串展开问题,按照[]前的数字展开字符 ...

  7. lintcode算法周竞赛

    ------------------------------------------------------------第七周:Follow up question 1,寻找峰值 寻找峰值 描述 笔记 ...

  8. [LintCode]——目录

    Yet Another Source Code for LintCode Current Status : 232AC / 289ALL in Language C++, Up to date (20 ...

  9. (lintcode全部题目解答之)九章算法之算法班题目全解(附容易犯的错误)

    --------------------------------------------------------------- 本文使用方法:所有题目,只需要把标题输入lintcode就能找到.主要是 ...

随机推荐

  1. Entity Framework 学习第二天 续

    今天来写一点不一样的删除,修改,查询 下面只写了几个方法 /// <summary> /// 根据删除条件进行删除 /// </summary> /// <param n ...

  2. mssql 动态添加数据库用户

    USE [master]GOCREATE LOGIN [admin] WITH PASSWORD=N'123456', DEFAULT_DATABASE=[test], CHECK_EXPIRATIO ...

  3. c++ 中static关键字

    static可以用于修饰普通的变量和函数,也可以用于修饰类的成员 普通应用 1.修饰普通变量 修饰全局变量:将变量的作用域限制在所属文件 修饰局部变量:将变量的生存周期延迟到程序结束 2.修饰普通函数 ...

  4. HTML5-地理定位

    HTML5 Geolocation(地理定位)用于定位用户的位置. 定位用户的位置 HTML5 Geolocation API 用于获得用户的地理位置. 鉴于该特性可能侵犯用户的隐私,除非用户同意,否 ...

  5. 基于PBOC电子钱包的消费过程详解

    智能卡金融行业应用电子钱包的消费交易流程,开发人员可参考 首先终端和卡片有一个共同的密钥叫做消费密钥:PurchKey (针对每种特定的交易,比如,圈存,消费,都有特定的密钥与之对应) 假设Purch ...

  6. JAVA内部类(转)

    源出处:JAVA内部类 在java语言中,有一种类叫做内部类(inner class),也称为嵌入类(nested class),它是定义在其他类的内部.内部类作为其外部类的一个成员,与其他成员一样, ...

  7. Team Homework #3 软件工程在北航——IloveSE

    任务要求: 采访以前上过北航  (计算机系/软件学院) 软件工程课的同学.现在上研/工作的也可以. 采访问题如下:* 平均每周花在这门课上的时间 (包括上课/作业/上机)    * 平均写的代码总行数 ...

  8. Class.forName("com.mysql.jdbc.Driver");的作用

    对于大的项目当然我们都已经有了原有基本框架,但是对于一些新的技术探讨的时候,我们还是直接调用Class.forName("com.mysql.jdbc.Driver")连接数据库进 ...

  9. android应用程序的安装方式与原理

    android应用程序的安装方式与原理 四种安装方式: 1.系统应用安装――开机时完成,没有安装界面 2.网络下载应用安装――通过market应用完成,没有安装界面 3.ADB工具安装――没有安装界面 ...

  10. android开发支付宝接口开发流程(密钥篇)

    参考博客:http://blog.it985.com/12276.html 官方下载地址:http://download.alipay.com/public/api/base/WS_MOBILE_PA ...