分支界限法 任务分配问题
2.5.1题目描述
分配问题要求将n个任务分配给n给人,每个人完成任务的代价不同,要求分配的结果最优,此题可以使用回溯求解。
2.5.2程序使用说明
Java环境1.8.0_111
IDE:eclipse
需要两个文件Node.java,Assignment.java直接编译两个文件,然后直接运行Assignment.java文件,在控制台查看结果。
2.5.3简要分析和设计
假设存在四个人a,b,c,d,任务1,任务2,任务3,任务4,和对应的代价矩阵如下
图二 矩阵(来源于算法设计与分析基础第三版)
采用分支界限法,需要计算最优边界Lb,Lb=已分配任务的代价+剩余未分配任务中最小的代价,然后构造状态空间树,上面例子的状态空间树如下:
图三 空间树(来源于算法设计与分析基础第三版)
开始节点表示还未给任何人分配任务,然后在开始节点的基础上寻找可扩展节点,由于此时a有四种选择,则有四个扩展节点,然后分别计算可扩展节点的lb,如果lb小于cost,则将其加入优先队列,然后从优先队列中选择一个最优的,作为新的扩展节点,然后在当前节点的基础上为继续进行上述步骤,当有一个节点的状态表示为已将四个节点分配完成,且花费的代价小于已有cost,则更新cost值,然后继续从优先队列里增加值和取值,直到优先队列为空,则最小花费即为最优选择。
2.5.4测试用例
{{9, 2, 7, 8},
{6, 4, 3, 7},
{5, 8, 1, 8},
{7, 6, 9, 4}}
结果:
人员以此选择工作为:2 1 3 4
最小花费:13
2.5.5源代码
目录结构:
package three.one;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.PriorityQueue;
/**
*
* @author ym
*
*/
public class Assignment {
//对应花费
private int[][] cost={
{9, 2, 7, 8},
{6, 4, 3, 7},
{5, 8, 1, 8},
{7, 6, 9, 4}
};
//构造比较函数
Comparator<Node> comparator = new Comparator<Node>() {
public int compare(Node o1, Node o2) {
return o1.getLb()-o2.getLb();
};
};
//存储优先队列
PriorityQueue<Node> priorityQueue = new PriorityQueue<Node>(comparator);
//记录当前最优解
int results = 0;
//存储节点
Node resultNode=null;
public Node initRootNode(){
Node root = new Node();
int lb=0;
for(int i=0;i<cost.length;i++){
int min=cost[i][0];
for(int j=1;j<cost[0].length;j++){
if(min>cost[i][j]){
min=cost[i][j];
}
}
lb+=min;
}
root.setLb(lb);//设置lb
return root;
}
/**
* 计算一个初始值上界
* @return
*/
public int mostBound(){
int bound=0;
for(int i=0;i<cost.length;i++){
int max=cost[i][0];
for(int j=1;j<cost[i].length;j++){
if(max<cost[i][j]){
max=cost[i][j];
}
}
bound+=max;
}
return bound;
}
//设置结果
public void setResults(int results) {
this.results = results;
}
/**
* 计算lb
* @param node
* @return
*/
public void calculateLb(Node node){
int lb=0;
ArrayList<Integer> upperNode =node.getUpperNode();
int size=upperNode.size();
for(int i=0;i<size;i++){//计算已选person的界
lb+=cost[i][upperNode.get(i)];
}
for(int i=size;i<cost.length;i++){//计算剩余person的最小界
int min=cost[i][0];
for(int j=1;j<cost[i].length;j++){
if(min>cost[i][j]){
min=cost[i][j];
}
}
lb+=min;
}
node.setLb(lb);//更新节点lb
}
/**
* 计算孩子节点
* @param node
* @return
*/
public ArrayList<Node> getChildNodes(Node node){
ArrayList<Node> childNodes = new ArrayList<Node>();//孩子节点
int i=node.getPerson()+1;
int order=0;
ArrayList<Integer> upperNode = node.getUpperNode();//获取已经选择的job
for(int j=0;j<cost[i].length;j++){
if(upperNode==null||order>=upperNode.size()){
Node temp =getNode( i,j,upperNode);//设置节点
childNodes.add(temp);
}
else{
if(order<upperNode.size()&&!upperNode.contains(j)){//构造子节点
Node temp =getNode(i,j,upperNode);//设置节点
childNodes.add(temp);
}
else
order++;
}
}
return childNodes;
}
/**
*
*
* @param i
* @param j
* @param list
* @return
*/
public Node getNode(int i,int j,ArrayList<Integer> list){
ArrayList<Integer> uppers=new ArrayList<Integer>();
if(list!=null&&list.size()>0){
uppers.addAll(list);
}
uppers.add(j);
Node temp = new Node(uppers);
temp.setPerson(i);
temp.setJob(j);
calculateLb(temp);
return temp;
}
/**
*
* @param node
*/
public void assiginment(Node node){
setResults(mostBound());//计算最大界
priorityQueue.add(node);
while(!priorityQueue.isEmpty()){
Node currentNode = priorityQueue.poll();
if(currentNode.getPerson()<cost.length-1){
ArrayList<Node> childNodes = getChildNodes(currentNode);
for(Node child:childNodes){
if(child.getLb()<results){
priorityQueue.add(child);
}
}
}
else{
if(currentNode.getLb()<results){
results=currentNode.getLb();
resultNode=currentNode;
}
}
}
}
public int getResults() {
return results;
}
public Node getResultNode() {
return resultNode;
}
public static void main(String[] args){
Assignment at = new Assignment();
Node root=at.initRootNode();
at.assiginment(root);
ArrayList<Integer> list = at.getResultNode().getUpperNode();
System.out.println("人员以此选择工作为:");
for(int i=0;i<list.size();i++){
System.out.print(" "+(list.get(i)+1));
}
System.out.println();
System.out.println("最小花费:");
System.out.print(at.getResults());
}
}
package three.one;
import java.util.ArrayList;
/**
* Node类
* @author ym
*
*/
public class Node{
int person=-1;
int job=-1;
int weight=0;
int lb=0;
ArrayList<Integer> upperNode;
public Node(){
}
public Node(ArrayList<Integer> upperNode){
this.upperNode=upperNode;
}
public int getPerson() {
return person;
}
public void setPerson(int person) {
this.person = person;
}
public int getJob() {
return job;
}
public void setJob(int job) {
this.job = job;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
public int getLb() {
return lb;
}
public void setLb(int lb) {
this.lb = lb;
}
public ArrayList<Integer> getUpperNode() {
return upperNode;
}
public void setUpperNode(ArrayList<Integer> upperNode) {
this.upperNode = upperNode;
}
}
分支界限法 任务分配问题相关推荐
- 算法分析与设计第二版(李春葆)第六章分支界限法
分支界限法类似于回溯法,一般回溯法目标是找出所有解,二分支界限法是找出满足条件的一个解或者最优解 算法 解空间树搜索方式 存储结点的常用数据结构 结点存储特性 常用应用 回溯法 深度优先搜索 栈 活结 ...
- 最大团问题-分支界限法
最大团问题-分支界限法 遍历所有点构造二叉树: 广度遍历树,遍历过程中判断当前结点的点数据时,是否构成完全子图,如果不能则只将右结点加入队列,每次选取队列中完全子图最大的结点作为活结点,无子结点时到达 ...
- 从0-1背包问题学习回溯法、分支界限法、动态规划
一.0-1背包问题的描述 下面将使用回溯法.分支界限法.动态规划法来分析和解决此问题. 二.回溯法 (1)算法步骤 (2)代码如下(没有裁剪函数): 用i和n来判断结束与否,是因为解空间结构是完全二叉 ...
- 单源路径分支界限java_单源最短路径-分支界限法
单源最短路径-分支界限法-优先队列式.这里使用无回路的有向图,便于构建树.构建好树后,从根结点作为起始源,加入结点队列,然后判断获取队列中最短的路径结点做为活结点,将活结点的所有子结点加入队列,移除活 ...
- 五大常用算法——分治法,动态规划,回溯法,分支界限法,贪心算法
(1) 分治法 将一个难以直接解决的大问题,分割成一些规模较小的相同问题 快速排序 快排也是分治的一个实例,快排每一趟会选定一个数,将比这个数小的放左面,比这个数大的放右面, 然后递归分治求解两个子区 ...
- 算法分析课设(十一)博物馆守卫问题、世界名画陈列馆问题(分支界限法)
免责声明 不想打字了.. 题目 在某博物馆中摆放了非常重要的文物,为了节省人力,该博物馆专门购买了警卫机器人来看管这些文物.该博物馆的房间排列整齐,房间的大小相同.每个警卫机器人能够巡查的范围除本身所 ...
- 算法设计-分支界限法——装载问题
算法介绍 分支界限法: 分支限界法常以广度优先或以最小耗费(最大效益)优先的方式搜索问题的解空间树. 在分支限界法中,每一个活结点只有一次机会成为扩展结点.活结点一旦成为扩展结点,就一次性产生其所有儿 ...
- 旅行售货员问题 java_旅行售货员问题-分支界限法
旅行售货员问题分支界限法 package test; import java.util.ArrayList; import java.util.Collections; import java.uti ...
- 分支界限法0 1背包 c语言,分支限界法之布线问题(1)
一.要求: 1.输入电路板区域n*m以及布线的起始位置和结束位置: 2.输出布线方案: 3.可以使用c或者vc实现 二.问题分析及实验原理: 在n*m的方格阵列中存在封锁区域(布线时必须绕开的区域), ...
- TSP旅行商问题之分支界限法法求解(C语言)
#include <stdio.h> #include <malloc.h>#define NoEdge 1000struct MinHeapNode {int lcost; ...
最新文章
- redis 发布订阅实际案例_Redis源码分析之发布订阅+慢查询+排序以及监视器
- 慢查询工具percona安装
- java jigsaw_60秒内使用Java 9的Project Jigsaw的JavaFX HelloWorld
- 计算机组成原理中英对照篇,信息科学系课程介绍(中英对照).doc
- CodeForces 580A Kefa and First Steps
- ELF文件和BIN文件
- 蚂蚁Service Mesh大规模落地实践与展望
- CoreGraphics之CGContextSaveGState与UIGraphicsPushContext
- mysql每天销售汇总_MySQL - 所有项目的每个总销售额
- azure vnc控制台_使用扩展和标签控制Azure成本
- 全面解读设备状态监测
- android 自定义viewgroup 布局,Android 自定义ViewGroup(一)
- Passive Aggressive Alogrithm
- 练习4闭合导线平差计算
- Web前端期末大作业-农产品一体化平台网页设计(HTML+CSS+JS)
- 个人网站建设记录 及Markdown使用实践
- 微信小程序 家校通 中小学家校联系电子作业系统
- 【Wordle】Day8:昨天忘了的后果就是今天输了
- 论文中流程图用什么软件画
- 万里长征——基础IO