java,优先队列的用法
像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(); } } }
在写这段代码过程中,注意需要用一个数组保存队列,否则容易出现错误。