package 分支限界法;

import java.util.LinkedList;
import java.util.Scanner; /*01背包问题*/
public class ZOPackage {
/*
* 主方法
*/
public static void main(String[] args) {
//输入数据
System.out.println("请输入背包的容量w和物品的个数n");
Scanner in = new Scanner(System.in);
int w = in.nextInt();// 背包的容量
int n = in.nextInt();// 物品的个数
int solution=-;
BLBag[] p = new BLBag[n];
System.out.println("请依次输入各个物品的名称s和重量w和价值v");
int value;
int weigth;
String pid;
for (int i = ; i < n; i++) {
pid = in.next();
weigth = in.nextInt();
value = in.nextInt();
p[i] = new BLBag(pid, weigth, value);
}
// 输入数据结束
/*
* 数据
* 001 16 45 002 15 25 003 15 25
*/
// 算法开始
//声明状态数组并初始化为空
Integer[] a=new Integer[n];
for(int i=;i<n;i++) a[i]=null;
//对p数组按权重排序
sort(p);
//打印结果
int haha=branchandlimit(p, w, a, solution);
System.out.println("最优解为:"+haha);
}
/*
* 权重排序,选择排序
*/
public static void sort(BLBag[] p) {
BLBag t;
for (int i = ; i < p.length; i++) {
int max = i;
t = p[i];
for (int j = i; j < p.length; j++) {
if (t.wi < p[j].wi) {
t = p[j];
max = j;
}
}
t = p[i];
p[i] = p[max];
p[max] = t; }
}
/*
* 求上界的函数 数组p 当前位置 当前背包重量 返回是最大价值(不包含背包的已有价值)
*/
public static double findbound(BLBag[] p,int i,int weight)
{
double value = ;
//将状态位后面的物品求贪心算法的解,上界函数的解为返回值+当前背包价值
forLOOP:for(int k=i;k<p.length;k++)//循环名字
{
//贪心算法求解问题(修改版)
if(p[k].weight<weight){
value=value+p[k].value;
weight=weight-p[k].weight;
}else{
double a=weight*p[k].wi;//当前价值
value=value+a;
weight=;
break forLOOP;//跳出循环
}
}
return value; }
/*
* 分支限界法主体 参数分别为物品数组p,重量,价值,状态数组,当前考虑位置i ,最优解
*/
public static int branchandlimit(BLBag[] p,int weight,Integer[] a,double solution)
{
//声明队列
LinkedList<Node> nodelist=new LinkedList<Node>();
LinkedList<Node> nodesolution=new LinkedList<Node>();
nodelist.add(new Node(, , ));
nodesolution.add(new Node(,,));
while(!nodelist.isEmpty())
{
//取出元素
Node node = nodelist.pop();
//判断条件,节点的不放入的最大值大于当前最优解,节点小于数组的长度
//这里不用等于,必须要大于
if(node.getUnbounvalue()+node.getCurrvalue()>solution && node.getIndex()<p.length)
{
//左节点
int leftWeight=node.getCurrweight()+p[node.getIndex()].weight;
int leftvalue=node.getCurrvalue()+p[node.getIndex()].value;
Node left=new Node(leftWeight, leftvalue, node.getIndex()+);
//设置左节点的父节点
left.setFather(node);
left.setIsleft(true);
//将左节点添加到最优解队列中
nodesolution.add(left);
//设置左节点的上界价值
left.setUnbounvalue((int)findbound(p, node.getIndex(), weight-node.getCurrweight()));
//左节点的重量小于等于背包的承重,且左节点的上界价值大于最优解
if(left.getCurrweight()<=weight && left.getUnbounvalue()+left.getCurrvalue()>solution)
{
//将节点加入队列中
nodelist.add(left);
a[node.getIndex()]=;
//将最优值重新赋值 条件就是节点的当前价值大于问题的最优解
if(left.getCurrvalue()>solution)
{
solution=left.getCurrvalue();
//System.out.println("放入的物品有:"+p[node.getIndex()].pid);
}
}
//右节点 右节点的设置不需要太多,和父节点差不多
Node right=new Node(node.getCurrweight(), node.getCurrvalue(), node.getIndex()+);
//将右节点添加到最优解队列中
right.setFather(node);
right.setIsleft(false);
nodesolution.add(right);
right.setUnbounvalue((int)findbound(p,node.getIndex(),weight-node.getCurrweight()));
//右节点的上界价值大于当前最优解
if(right.getUnbounvalue()+node.getCurrvalue()>solution)
{
//添加右节点
nodelist.add(right);
a[node.getIndex()]=;
}
}
} /*
* 调用最优解方法
*/
pr(nodesolution,(int)solution,p);
//返回最优解 return (int) solution;
}
/**
*
* @Description: 求解最优解的方法
* @param @param nodesolution
* @return void
* @throws
* @author yanyu
* @date 2018年5月21日
*/
//参数为
public static void pr(LinkedList<Node> nodesolution,int solution,BLBag[] p)
{
int[] a=new int[p.length];
Node prnode=null;
//从list中循环遍历最优解的节点
for(Node node:nodesolution)
{
if(node.getCurrvalue()==solution){
//System.out.println("最优解的父节点的索引为:"+node.getFather().getIndex());
prnode=node;
}
}
//循环遍历最优节点的父节点,判断其是否为左节点
while (prnode.getFather()!=null)
{
if(prnode.isIsleft())
{
a[prnode.getIndex()-]=;
}
prnode=prnode.getFather();
}
//打印
for(int i=;i<p.length;i++)
{
if(a[i]==) System.out.println("放入了物品:"+p[i].pid);
}
} } /*
* 背包类
*/
class BLBag {
public int weight;// 重量
public int value;// 价值
public double wi;// 权重
public String pid;// 背包名称
public BLBag(String pid, int weight, int value) {
this.weight = weight;
this.value = value;
this.pid = pid;
this.wi = (double) value / weight;
}
}
/**
*
* ClassName: Node
* @Description: 节点类
* @author yanyu
* @date 2018年5月17日
*/
class Node
{
//当前物品的属性
private int currweight;//当前重量
private int currvalue;//当前价值
private int unbounvalue;//上界价值
private int index;//索引
private Node father;//父节点
private boolean isleft;//是否为左节点
public boolean isIsleft() {
return isleft;
}
public void setIsleft(boolean isleft) {
this.isleft = isleft;
}
public Node getFather() {
return father;
}
public void setFather(Node father) {
this.father = father;
}
public int getCurrweight() {
return currweight;
}
public void setCurrweight(int currweight) {
this.currweight = currweight;
}
public int getCurrvalue() {
return currvalue;
}
public void setCurrvalue(int currvalue) {
this.currvalue = currvalue;
}
public int getUnbounvalue() {
return unbounvalue;
}
public void setUnbounvalue(int unbounvalue) {
this.unbounvalue = unbounvalue;
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
//构造函数
public Node(int currweight,int currvalue,int index)
{
this.currweight=currweight;
this.currvalue=currvalue;
this.index=index;
}
}
/******
运行结果
请输入背包的容量w和物品的个数n
10 5
请依次输入各个物品的名称s和重量w和价值v
p1 2 6
p2 2 3
p3 6 5
p4 5 4
p5 4 6
放入了物品:p1
放入了物品:p2
放入了物品:p5
最优解为:15
*********/
package 回溯法;

import java.util.Arrays;
import java.util.Collections;
import java.util.Scanner; public class ZOPakage {
public static void main(String[] args) {
System.out.println("请输入背包的容量w和物品的个数n");
Scanner in = new Scanner(System.in);
int w = in.nextInt();// 背包的容量
int n = in.nextInt();// 物品的个数
BLBag[] bags = new BLBag[n];
System.out.println("请依次输入各个物品的名称s和重量w和价值v");
int value;
int weigth;
String pid;
for (int i = 0; i < n; i++) {
pid = in.next();
weigth = in.nextInt();
value = in.nextInt();
bags[i] = new BLBag(pid, weigth, value);
}
HSSFProblem problem = new HSSFProblem(bags, w);
System.out.println("最优解为:"+problem.solve(0));
}
} class BLBag implements Comparable<BLBag> {
/** 物品名字*/
private String name;
/** 物品重量 */
private int weight;
/** 物品价值 */
private int value;
/** 单位重量价值 */
private int unitValue; public BLBag(String name,int weight, int value) {
this.weight = weight;
this.value = value;
this.name = name;
this.unitValue = (weight == 0) ? 0 : value / weight;
} public String getname() {
return name;
} public void setname(int weight) {
this.name = name;
} public int getWeight() {
return weight;
} public void setWeight(int weight) {
this.weight = weight;
} public int getValue() {
return value;
} public void setValue(int value) {
this.value = value;
} public int getUnitValue() {
return unitValue;
} @Override
public int compareTo(BLBag snapsack) {
int value = snapsack.unitValue;
if (unitValue > value)
return 1;
if (unitValue < value)
return -1;
return 0;
}
} class HSSFProblem { // 待选择的物品
private BLBag[] bags;
// 背包的总承重
private int totalWeight;
// 背包的当前承重
private int currWeight;
// 待选择物品数量
private int n;
// 放入物品后背包的最优价值
private int bestValue;
// 放入物品和背包的当前价值
private int currValue; public HSSFProblem(BLBag[] bags, int totalWeight) {
this.bags = bags;
this.totalWeight = totalWeight;
this.n = bags.length; // 物品依据单位重量价值从大到小进行排序
Arrays.sort(bags, Collections.reverseOrder());
} public int solve(int i) { // 当没有物品可以放入背包时,当前价值为最优价值
if (i >= n) {
bestValue = currValue;
return bestValue;
} // 首要条件:放入当前物品,判断物品放入背包后是否小于背包的总承重
if (currWeight + bags[i].getWeight() <= totalWeight) {
// 将物品放入背包中的状态
currWeight += bags[i].getWeight();
currValue += bags[i].getValue(); // 选择下一个物品进行判断
bestValue = solve(i + 1); // 将物品从背包中取出的状态
currWeight -= bags[i].getWeight();
currValue -= bags[i].getValue();
} // 次要条件:不放入当前物品,放入下一个物品可能会产生更优的价值,则对下一个物品进行判断
// 当前价值+剩余价值<=最优价值,不需考虑右子树情况,由于最优价值的结果是由小往上逐层返回,
// 为了防止错误的将单位重量价值大的物品错误的剔除,需要将物品按照单位重量价值从大到小进行排序
if (currValue + getSurplusValue(i + 1) > bestValue) {
// 选择下一个物品进行判断
bestValue = solve(i + 1);
}
return bestValue;
} // 获得物品的剩余总价值
public int getSurplusValue(int i) {
int surplusValue = 0;
for (int j = i; j < n; j++)
surplusValue += bags[i].getValue();
return surplusValue;
} }
/**
运行结果
请输入背包的容量w和物品的个数n
10 5
请依次输入各个物品的名称s和重量w和价值v
p1 2 6
p2 2 3
p3 6 5
p4 5 4
p5 4 6
最优解为:15
**/

分支限界详解:https://www.cnblogs.com/RB26DETT/p/10982687.html#top

动态规划、分支限界、回溯对比:https://www.jianshu.com/p/270acca3e6fa

01背包问题_回溯法&分支限界法的更多相关文章

  1. 01背包问题(回溯法)python实现

    接上一篇,相同的01背包问题,上一篇採用动态规划的方法,如今用回溯法解决. 回溯法採用深度优先策略搜索问题的解.不多说.代码例如以下: bestV=0 curW=0 curV=0 bestx=None ...

  2. n皇后问题_回溯法

    具体问题如下图 先看一下4*4的回溯过程 程序结束条件: 一组解:设标志,找到一解后更改标志,以标志做为结束循环的条件. 所有解:k=0 判断约束函数判断第k个后能不能放在x[k]处 两个皇后不能放在 ...

  3. python 回溯法 子集树模板 系列 —— 3、0-1背包问题

    问题 给定N个物品和一个背包.物品i的重量是Wi,其价值位Vi ,背包的容量为C.问应该如何选择装入背包的物品,使得放入背包的物品的总价值为最大? 分析 显然,放入背包的物品,是N个物品的所有子集的其 ...

  4. 0-1背包问题——回溯法求解【Python】

    回溯法求解0-1背包问题: 问题:背包大小 w,物品个数 n,每个物品的重量与价值分别对应 w[i] 与 v[i],求放入背包中物品的总价值最大. 回溯法核心:能进则进,进不了则换,换不了则退.(按照 ...

  5. Python基于回溯法解决01背包问题实例

    Python基于回溯法解决01背包问题实例 这篇文章主要介绍了Python基于回溯法解决01背包问题,结合实例形式分析了Python回溯法采用深度优先策略搜索解决01背包问题的相关操作技巧,需要的朋友 ...

  6. YTU 2335: 0-1背包问题

    2335: 0-1背包问题 时间限制: 1 Sec  内存限制: 128 MB 提交: 15  解决: 12 题目描述 试设计一个用回溯法搜索子集空间树的函数.该函数的参数包括结点可行性判定函数和上界 ...

  7. 0-1背包问题与N皇后问题的纠结

    昨日同学要我帮他看一道算法,如下: 是不是乍一看是“0-1背包”问题呀,我也这么想,于是就这么兴致勃勃的开始用这个想法去思考怎么算.但是算法也忘得差不多,回去赶紧补补,也趁着这次机会好好复习一下算法, ...

  8. NPC问题及其解决方法(回溯法、动态规划、贪心法、深度优先遍历)

    NP问题(Non-deterministic Polynomial ):多项式复杂程度的非确定性问题,这些问题无法根据公式直接地计算出来.比如,找大质数的问题(有没有一个公式,你一套公式,就可以一步步 ...

  9. 回溯法最优装载问题(java)

    1.问题描述:      有一批共有 n 个集装箱要装上两艘载重量分别为 c1 和 c2 的轮船,其中集装箱 i 的重量为 w[i], 且重量之和小于(c1 + c2).装载问题要求确定是否存在一个合 ...

随机推荐

  1. 腾讯云Windows Server下nodejs websocket ssl配置

    1.从腾讯云申请SSL证书,下载解压,得到如下文件: 2.nodejs代码: // wss.js const fs = require('fs'); // 一些配置信息 const cfg = { p ...

  2. Flask - app.debug=True,python manage.py和export FLASK_DEBUG=True,flask run的不同。

    TL;DR,可以直接看下面的总结 问题1:为什么app.config['DEBUG'] = True,然后flask run并没有开启debugger和reloading,而直接运行脚本(python ...

  3. ANSYS单元应用简介1

    目录 1. LINK单元 2. BEAM单元 3. PLANE单元 4. SHELL单元 5. SOLIDE单元 6. COMBIN单元 ANSYS中的单元针对不同的应用对象,有着不同的选择方法,下面 ...

  4. Mac 系统上有趣的插件

    1.微信小助手:https://github.com/TKkk-iOSer/WeChatPlugin-MacOS 作用:开启消息撤回拦截,设置自动回复,远程登录Mac,微信多开,免认证登录.... 2 ...

  5. 什么是SOA架构

    什么是SOA架构 SOA是Service-Oriented Architecture的首字母简称,它是一种支持面向服务的架构样式.从服务.基于服务开发和服务的结果来看,面向服务是一种思考方式.其实SO ...

  6. C. Swap Letters 01字符串最少交换几次相等

    C. Swap Letters time limit per test 2 seconds memory limit per test 256 megabytes input standard inp ...

  7. 夯实Java基础(二十二)——Java8新特性之Lambda表达式

    1.前言 Java 8于14年发布到现在已经有5年时间了,经过时间的磨练,毫无疑问,Java 8是继Java 5(发布于2004年)之后的又一个非常最重要的版本.因为Java 8里面出现了非常多新的特 ...

  8. matplotlib常见操作

    import osimport numpy as npfrom PIL import Imageimport matplotlib.pyplot as plt img = Image.open(os. ...

  9. Microsoft Cortana移动版除美国市场外不再可用

    导读 先前已经透露,Microsoft Cortana的移动版本已不复存在.目前,Microsoft Cortana在移动设备上的多个国家和地区中支持多种语言.微软的Cortana移动版本不再支持的市 ...

  10. vs2013中配置SQLite数据库

    转载:https://maplefan.com/index.php/2019/08/14/visual-studio-2013%e9%85%8d%e7%bd%aesqlite3%e7%9a%84%e6 ...