像C++語言一樣,java中,也有包裝好的優先隊列類PriorityQueue。
用法如下(模板代碼):
工作安排問題:
問題描述:設有n件工作分配給n個人,將工作i分配給第j個人所需的費用為cij。試設計一個算法,為每個人都分配一件不同的工作,並使得總費用達到最小。
輸入:第1行有1個正整數n(1≤n≤20),接下來的n行,每行n個數,表示工作費用。
輸出:計算的最小總費用
樣例輸入: 樣例輸出:
3 9
10 2 3
2 3 4
3 4 5
使用優先級分支限界的方法,很容易解決這道題目,但是在寫代碼的過程中,是很容易出現錯誤,因此需要注意!!!。
package com.KongLong; import java.util.Comparator; import java.util.PriorityQueue; import java.util.Queue; import java.util.Scanner; class Money { int CurrentMoney;//當前費用; int PossibleMoney;//當前結點可能最小的費用 int locat;//當前的行坐標 boolean vis[] = new boolean[25]; } class Cmp implements Comparator<Money>//優先級排序 { public int compare(Money o1, Money o2) { if(o1.PossibleMoney > o2.PossibleMoney) { return 1; } else if(o1.PossibleMoney == o2.PossibleMoney) { return 0; } else { return -1; } } } public class Main { static int N; static final int MAX = 25; static int money[][] = new int[MAX][MAX];//鄰接矩陣 static Money M[] = new Money[MAX];//在隊列中使用 static int cnt = 0; static Queue<Money> que = new PriorityQueue<Money>(MAX,new Cmp());//優先隊列 static int result; public static void main(String []args) { init(); Scanner cin = new Scanner(System.in); N = cin.nextInt(); cnt = 0; result = 99999999; for(int i = 0; i < N; i++) { for(int j = 0; j < N; j++) { money[i][j] = cin.nextInt(); } } for(int i = 0; i < N; i++) { M[cnt].CurrentMoney = money[0][i]; M[cnt].locat = 0; M[cnt].vis[i] = true; M[cnt].PossibleMoney = M[cnt].CurrentMoney+Bound(1); //System.out.println(M[cnt].PossibleMoney); que.add(M[cnt]); cnt++; } while(!que.isEmpty())//隊列為空判斷 { Money a = new Money(); a = que.poll(); //System.out.println(a.CurrentMoney + ">>>>>>> " + a.PossibleMoney + ">>> " + a.locat); if(a.locat == N-1 && a.CurrentMoney < result)//界限 { result = a.CurrentMoney; //System.out.println("000"); continue; } else if(a.locat == N-1)//界限 { continue; } else if(a.PossibleMoney > result)//剪枝 { break; } for(int i = 0; i < N; i++) { if(a.vis[i] == true) { continue; } M[cnt].CurrentMoney = a.CurrentMoney+money[a.locat+1][i]; M[cnt].vis[i] = true; for(int j = 0; j < N; j++) { if(a.vis[j] == true) { M[cnt].vis[j] = true; } //System.out.println(M[cnt].vis[j]); } M[cnt].locat = a.locat+1; M[cnt].PossibleMoney = M[cnt].CurrentMoney+Bound(a.locat+2); //System.out.println(M[cnt].CurrentMoney + " >>>>>>>>>>> " + M[cnt].PossibleMoney + " yyyyy "); //M[cnt].vis[i] = true; que.add(M[cnt]); cnt++; } } System.out.println(result); } static int Bound(int j)//當前結點的最小費用 { int sum = 0; for(int i = j; i < N; i++) { int Min = 99999999; for(int k = 0; k < N; k++) { if(M[cnt].vis[k] == true) { //System.out.println(k + "k"); continue; } Min = Math.min(Min, money[i][k]); } sum += Min; } //System.out.println(j + "///// " + sum); return sum; } static void init() { for(int i = 0; i < MAX; i++) { M[i] = new Money(); } } }
在寫這段代碼過程中,注意需要用一個數組保存隊列,否則容易出現錯誤。