背包问题(Knapsack problem)采用动态规划求解
问题说明:
假设有一个背包的负重最多可达8公斤,而希望在背包中装入负重范围内可得之总价物
品,假设是水果好了,水果的编号、单价与重量如下所示:
0
李子
4KG
NT$4500
1
苹果
5KG
NT$5700
2
橘子
2KG
NT$2250
3
草莓
1KG
NT$1100
解法背包问题是关于最佳化的问题,要解最佳化问题可以使用「动态规划」 (Dynamicprogramming) ,从空集合开始,每增加一个元素就先求出该阶段的最佳解,直到所有的元素加入至集合中,最后得到的就是最佳解。
下面我们看下代码:
- /*
- 问题:
- 假设有一个背包的负重最多可达8公斤,而希望在背包中装入负重范围内可得之总价物品
- 算法说明:
- 采用动态规划,在当前阶段求解出最好的解,如此反复
- 日期:2013/8/18
- 张威
- */
- #include <iostream>
- #include <time.h>
- using namespace std;
- #define MAXSIZE 8
- //定义全局变量
- char name[][] = {"李子","苹果","橘子","草莓","甜瓜"};//水果名称
- int wight[] = {,,,,};//单个水果所占斤数
- int price[] = {,,,,};//单个水果的价值
- int perkg_price[];//每斤水果的价钱
- int perkg_num[] = {,,,,};
- void GetNmae(int num)
- {
- for (int i = ;i <= ;i++)
- {
- cout<<name[num][i];
- }
- }
- void GetBestAnswer(int currentwigh)
- {
- //判断递归终止条件
- if (currentwigh >= MAXSIZE)
- {
- cout<<"包裹已经满了,无法再装进东西"<<endl;
- }
- else
- {
- //check用来表证到底剩下来的物品里面还有没有能装进去背包里的
- bool check = true;
- int i = ;
- for (;i <= ;i++)
- {
- //若是没有进入到这个条件内,说明剩下来的物品的重量都超过了背包剩余重量,到此结束.否则i就代表当前所能选中的最优解
- if (wight[perkg_num[i]] <= MAXSIZE-currentwigh)
- {
- check = false;
- break;
- }
- }
- if (check == true)
- {
- cout<<"已经装不进去任何水果了"<<endl;
- }
- else
- {
- //得到最优解,并且将当前重量增加,进入下一次递归
- currentwigh += wight[perkg_num[i]];
- cout<<"购买了";
- GetNmae(perkg_num[i]);
- cout<<endl;
- GetBestAnswer(currentwigh);
- }
- }
- }
- int main()
- {
- //计算出每斤水果的价钱,便于动态规划时求出当前最佳解
- for (int i = ;i <= ;i++)
- {
- perkg_price[i] = price[i] / wight[i];
- }
- //对perkg_num进行排序,同时保证单价和perkg_num之间的一一对应关系.即两个数组要同时变化
- //采用的是冒泡排序,在元素进行交换时perkg_num和perkg_price同时变化
- for (int i = ;i <= ;i++)
- {
- for (int j = i;j <= ;j++)
- {
- if (perkg_price[j] < perkg_price[j+])
- {
- int temp1 = perkg_price[j];
- int temp2 = perkg_num[j];
- perkg_price[j] = perkg_price[j+];
- perkg_price[j+] = temp1;
- perkg_num[j] = perkg_num[j+];
- perkg_num[j+] = temp2;
- }
- }
- }
- //开始计算求解
- GetBestAnswer();
- return ;
- }
背包问题
在这里,算法的主要思想有两个:1.通过冒泡排序得到一个单价表,并将物品的ID与之配对起来.这样我们在每次的递归中通过ID找到物品的相应属性,筛选出当前步骤的最优解出来
2.通过递归,传递当前的重量,得到还剩余的重量,根据前面的单价表,筛选出可选的最优解,然后将重量变化进入下一次递归.
这是最大空间为8的运行结果: 这是最大空间为29的运行结果:
下面附上指导书上面的代码:
- #include <stdio.h>
- #include <stdlib.h>
- #define LIMIT 8
- // 重量限制
- #define N 5
- // 物品种类
- #define MIN 1
- // 最小重量
- struct body {
- char name[];
- int size;
- int price;
- };
- 背
- 包
- 负
- 重
- valu
- e
- item
- 0
- 背
- 包
- 负
- 重
- valu
- e
- item
- 0
- typedef struct body object;
- int main(void) {
- int item[LIMIT+] = {};
- int value[LIMIT+] = {};
- int newvalue, i, s, p;
- object a[] = {{"李子", , },
- {"苹果", , },
- {"橘子", , },
- {"草莓", , },
- {"甜瓜", , }};
- for(i = ; i < N;i++) {
- for(s = a[i].size; s <= LIMIT;s++) {
- p = s - a[i].size;
- newvalue = value[p] + a[i].price;
- if(newvalue > value[s]) {// 找到阶段最佳解
- value[s] = newvalue;
- item[s] = i;
- }
- }
- }
- printf("物品\t价格\n");
- for(i = LIMIT;i >= MIN;i = i - a[item[i]].size) {
- printf("%s\t%d\n",
- a[item[i]].name, a[item[i]].price);
- }
- printf("合计\t%d\n", value[LIMIT]);
- return ;
- }
- Java
- class Fruit {
- private String name;
- private int size;
- private int price;
- public Fruit(String name,int size, int price){
- this.name = name;
- this.size = size;
- this.price = price;
- }
- public String getName(){
- return name;
- }
- public int getPrice(){
- return price;
- }
- public int getSize() {
- return size;
- }
- }
- public class Knapsack {
- public static void main(String[] args){
- final int MAX = ;
- final int MIN = ;
- int[] item = new int[MAX+];
- int[] value = new int[MAX+];
- Fruit fruits[] = {
- new Fruit("李子", , ),
- new Fruit("苹果", , ),
- new Fruit("橘子", , ),
- new Fruit("草莓", , ),
- new Fruit("甜瓜", , )};
- for(int i = ; i < fruits.length;i++) {
- for(int s = fruits[i].getSize(); s <= MAX;s++){
- int p = s - fruits[i].getSize();
- int newvalue = value[p] +
- fruits[i].getPrice();
- if(newvalue > value[s]) {// 找到阶段最佳解
- value[s] = newvalue;
- item[s] = i;
- }
- }
- }
- System.out.println("物品\t价格");
- for(int i = MAX;
- i >= MIN;
- i = i - fruits[item[i]].getSize()) {
- System.out.println(fruits[item[i]].getName()+
- "\t" + fruits[item[i]].getPrice());
- }
- System.out.println("合计\t" + value[MAX]);
- }
- }
指导书上面的代码
我居然没想到使用结构体,失策失策,都没用什么高级点的数据结构,看起来貌似很复杂的样子.明天再看
背包问题(Knapsack problem)采用动态规划求解的更多相关文章
- 对背包问题(Knapsack Problem)的算法探究
对背包问题(Knapsack Problem)的算法探究 至繁归于至简,这次自己仍然用尽可能易理解和阅读的解决方式. 1.问题说明: 假设有一个背包的负重最多可达8公斤,而希望在背包中装入负重范围内可 ...
- 【优化算法】变邻域搜索算法解决0-1背包问题(Knapsack Problem)代码实例 已
01 前言 经过小编这几天冒着挂科的风险,日日修炼,终于赶在考试周中又给大家更新了一篇干货文章.关于用变邻域搜索解决0-1背包问题的代码.怎样,大家有没有很感动? 02 什么是0-1背包问题? 0-1 ...
- 动态规划-背包问题 Knapsack
2018-03-15 13:11:12 背包问题(Knapsack problem)是一种组合优化的NP完全问题.问题可以描述为:给定一组物品,每种物品都有自己的重量和价格,在限定的总重量内,我们如何 ...
- knapsack problem 背包问题 贪婪算法GA
knapsack problem 背包问题贪婪算法GA 给点n个物品,第j个物品的重量,价值,背包的容量为.应选哪些物品放入包内使物品总价值最大? 规划模型 max s.t. 贪婪算法(GA) 1.按 ...
- 动态规划法(四)0-1背包问题(0-1 Knapsack Problem)
继续讲故事~~ 转眼我们的主人公丁丁就要离开自己的家乡,去大城市见世面了.这天晚上,妈妈正在耐心地帮丁丁收拾行李.家里有个最大能承受20kg的袋子,可是妈妈却有很多东西想装袋子里,已知行李的编 ...
- 0-1背包问题——动态规划求解【Python】
动态规划求解0-1背包问题: 问题:背包大小 w,物品个数 n,每个物品的重量与价值分别对应 w[i] 与 v[i],求放入背包中物品的总价值最大. 动态规划核心:计算并存储小问题的最优解,并将这些最 ...
- 0-1背包问题(0-1 knapsack problem)
0-1背包问题描述:一个正在抢劫商店的小偷发现了n个商品,第i个商品价值 vi 美元,重 wi 磅,vi 和 wi 都是整数.这个小偷希望拿走价值尽量高的商品,但他的背包最多能容纳 S 磅重的商品,S ...
- FZU 2214 Knapsack problem 01背包变形
题目链接:Knapsack problem 大意:给出T组测试数据,每组给出n个物品和最大容量w.然后依次给出n个物品的价值和体积. 问,最多能盛的物品价值和是多少? 思路:01背包变形,因为w太大, ...
- [DP] The 0-1 knapsack problem
Give a dynamic-programming solution to the 0-1 knapsack problem that runs in O(nW) time, where n is ...
随机推荐
- Estimating Project Costs
The Wideman Comparative Glossary of Common Project Management Terms describes estimating cost as, &q ...
- imx6 MFG TOOL 分析
之前分析过mfgtool的内容,最近从官网下载,返现新版的mfgtool工具将imx6各种版本的linux/android都使用一个工具进行烧录.所以从新分析一下. 新版与旧版的一个区别是烧写使用的u ...
- Spring AOP 实现原理与 CGLIB 应用
https://www.ibm.com/developerworks/cn/java/j-lo-springaopcglib/ AOP(Aspect Orient Programming),也就是面向 ...
- hibernate一对多注解
package net.zmcheng.model; import java.util.HashSet;import java.util.Set; import javax.persistence.C ...
- glusterFS安装维护文档
.规划: .依赖包 yum install libibverbs librdmacm xfsprogs nfs-utils rpcbind libaio liblvm2app lvm2-devel l ...
- 从 Vue 1.x 迁移
FAQ 哇,非常长的一页!是否意味着 Vue2.0 已经完全不同了呢,是否需要从头学起呢,Vue1.0 的项目是不是没法迁移了? 非常开心地告诉你,并不是! 几乎90%的 API 和核心概念都没有变. ...
- javascript设计模式学习之九——命令模式
一.命令模式使用场景及定义 命令模式常见的使用场景是:有时候需要向某些对象发送请求,但是并不知道请求的接受者是谁,也不知道请求的具体操作是什么.此时希望用一种松耦合的方式来设计程序,使得请求的发送者和 ...
- Windows 7 / Windows 10 安装 IPX/SPX
以我的系统为例: Windows 7/10 x64 首先下载 NWLINK IPX/SPX 驱动(这是 Microsoft 对 IPX/SPX 的实现.) http://pan.baidu.com/s ...
- nsstring基本数据类型的包装类
// // main.m // 10-基本数据类型的包装类 // // Created by apple on 14-3-20. // Copyright (c) 2014年 apple. A ...
- 离线下载Windows 调试符号 Symbols
公司开发机没有不能连接到互联网.调试程序时那些Windows模块(如ntdll.dll)不能加载符号,而程序总是崩在这些模块里.想看一眼到底崩在了什么地方. 需要把对应的符号下载下来. 使用工具sym ...