1. 程式人生 > >分支界限法 任務分配問題

分支界限法 任務分配問題

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;

}

}