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. Python爬虫教程:requests模拟登陆github

    1. Cookie 介绍 HTTP 协议是无状态的.因此,若不借助其他手段,远程的服务器就无法知道以前和客户端做了哪些通信.Cookie 就是「其他手段」之一. Cookie 一个典型的应用场景,就是 ...

  2. VBA 学习笔记 - 变量与常量

    学习资料:https://www.yiibai.com/vba/vba_variables.html 变量和常量命名规则 必须以字母开头 不能包含空格.句点(.).感叹号(!)或字符@,&,$ ...

  3. oracle学习笔记(十四) 数据库对象 索引 视图 序列 同义词

    数据库对象 用户模式:指数据库用户所创建和存储数据对象的统称.在访问其它用户模式的数据库对象时需加上用户模式. 如:scott.emp, scott.dept等. 数据库对象包括:表.视图.索引.序列 ...

  4. 关于archive(feature)

    配置如下archive命令,可以记录登录到设备,具体配置了哪些命令: R3(config)#archiveR3(config-archive)#log configR3(config-archive- ...

  5. vc code js 配置

    VSCode (for JS develop) https://www.jianshu.com/p/c56ea43b2b34 前言 编辑器之间的竞争一直也十分的激烈,用过Webstom,Hbuilde ...

  6. Java学习资源 - 测试

    JUnit注解解释 1. @Test : 测试方法,测试程序会运行的方法,后边可以跟参数代表不同的测试,如(expected=XXException.class) 异常测试,(timeout=xxx) ...

  7. SSD算法

    SSD算法 2016  出的目标检测算法 SSD效果主要有三点: 1.多尺度 2.设置了多种宽高比的(anchor box)default box 3.数据增强 1.1  设置 default box ...

  8. SpringBoot常用注解解析

    @RestController 将返回的对象数据直接以 JSON 或 XML 形式写入 HTTP 响应(Response)中.绝大部分情况下都是直接以 JSON 形式返回给客户端,很少的情况下才会以 ...

  9. 实现纸牌游戏的随机抽牌洗牌过程(item系列几个内置方法的实例)

    实现纸牌游戏的随机抽牌洗牌过程(item系列几个内置方法的实例) 1.namedtuple:命名元组,可以创建一个没有方法只有属性的类 from collections import namedtup ...

  10. Java自学-集合框架 ArrayList和LinkedList的区别

    ArrayList和LinkedList的区别 步骤 1 : ArrayList和LinkedList的区别 ArrayList ,插入,删除数据慢 LinkedList, 插入,删除数据快 Arra ...