1. 程式人生 > >演算法設計與分析: 6-18 一般解空間的優先佇列式分支限界法

演算法設計與分析: 6-18 一般解空間的優先佇列式分支限界法

6-18 一般解空間的優先佇列式分支限界法

問題描述

試設計一個用優先佇列式分支限界法搜尋一般解空間的函式。該函式的引數包括結點可 行性判定函式和上界函式等必要的函式,並將此函式用於解佈線問題。
印刷電路板將佈線區域劃分成 n×m 個方格陣列如圖(a)所示。精確的電路佈線問題要求 確定連線方格 a 的中點到方格 b 的中點的最短佈線方案。在佈線時,電路只能沿直線或直角佈線,如圖(b)所示。為了避免線路相交,已布了線的方格做了封鎖標記,其它線路不允許穿過被封鎖的方格。

電路板佈線

對於給定的佈線區域,程式設計計算最短佈線方案。

資料輸入:
第一行有 3 個正整數 n,m,k,分別表示佈線區域方格陣列的行數,列數和封閉的方格數。接下來的 k 行中,每行 2 個正整數,表示被封閉的方格所在的行號和列號。最後的 2 行,每行也有 2 個正整數,分別表示開始佈線的方格(p,q)和 結束佈線的方格(r,s)。

Java

package Chapter6FenZhiXianJieFa;

import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Scanner;

public class YiBanJieKongJianYouXianDuiLie {

    private static class HeapNode implements Comparable{
        int row,col,len;

        public int compareTo(Object o){
            HeapNode heapNode = (HeapNode) o;
            int
result = Integer.compare(len, heapNode.len); return result; } } private static class Maze{ int n,m; boolean found; int[][] grid; int pathLen; HeapNode start,finish; HeapNode[] offset = new HeapNode[4]; HeapNode[] path; private
void newHeap(){ H = new PriorityQueue<>(100000); } private void init(){ //設定方格陣列圍牆 for(int i=0; i<=m+1; i++) grid[0][i]=grid[n+1][i]=1;//頂部和底部 for(int i=0; i<=n+1; i++) grid[i][0]=grid[i][m+1]=1;//左翼和右翼 //初始化相對位移 for(int i=0; i<4; i++) offset[i] = new HeapNode(); offset[0].row=0; offset[0].col=1;//右 offset[1].row=1; offset[1].col=0;//下 offset[2].row=0; offset[2].col=-1;//左 offset[3].row=-1; offset[3].col=0;//上 E = new HeapNode(); E.row = start.row; E.col = start.col; E.len = 0; grid[start.row][start.col] = 2; } //葉結點判定 private boolean answer(HeapNode E){ return false; } //儲存最優解 private void save(HeapNode E){ } private int f(int n, HeapNode E){ return 1; } private int g(int n, HeapNode E){ return 4; } //產生新結點 private void newNode(HeapNode E, int i){ N = new HeapNode(); N.row = E.row+offset[i-1].row; N.col = E.col+offset[i-1].col; } //可行性約束 private boolean constrain(HeapNode E){ return grid[E.row][E.col]==0; } //邊界約束 private boolean bound(HeapNode E){ if(!found) found=(E.row==finish.row && E.col==finish.col); return true; } private void addLiveNode(HeapNode N, HeapNode E, int i){ grid[N.row][N.col] = grid[E.row][E.col]+1; N.len = grid[N.row][N.col]; if(!found) H.add(N); } private boolean getNext(){ // if(found || H.isEmpty()) return false; if(found) return false; E = H.poll(); return true; } private void output(){ if(!found) {System.out.println("No path!"); return;} //構造最優解 pathLen = grid[finish.row][finish.col]-2; path = new HeapNode[pathLen]; for(int i=0; i<pathLen; i++) path[i] = new HeapNode(); //從目標位置finish開始向起始位置回溯 HeapNode N = new HeapNode(); HeapNode E = finish; for(int j=pathLen-1; j>=0; j--){ path[j].row = E.row; path[j].col = E.col; //找前驅位置 for(int i=0; i<4; i++){ N.row = E.row+offset[i].row; N.col = E.col+offset[i].col; if(grid[N.row][N.col] == j+2) break; } E.row = N.row;//向前移動 E.col = N.col;//向前移動 } System.out.println(pathLen); System.out.println(start.row+" "+start.col); for(int j=0; j<pathLen; j++) System.out.println(path[j].row+" "+path[j].col); } private void pqbb(){ newHeap(); E = new HeapNode(); init(); //搜尋一般解空間樹 while (true){ if(answer(E)) save(E); else for(int i=f(n,E); i<=g(n,E); i++){ newNode(E,i); if(constrain(N) && bound(N)) addLiveNode(N,E,i); } //取下一擴充套件結點 if(!getNext()) break; } output(); } } private static HeapNode E,N; private static Queue<HeapNode> H; public static void main(String[] args){ int n,m,k,a,b; Scanner input = new Scanner(System.in); while (true){ n = input.nextInt(); m = input.nextInt(); k = input.nextInt(); Maze X = new Maze(); X.n=n; X.m=m; X.found=false; X.grid = new int[n+2][m+2]; for(a=0; a<n+2; a++) for(b=0; b<m+2; b++) X.grid[a][b] = 0; for(int i=k; i>=1; i--){ a = input.nextInt(); b = input.nextInt(); X.grid[a][b] = 1; } X.start = new HeapNode(); X.finish = new HeapNode(); X.start.row = input.nextInt(); X.start.col = input.nextInt(); X.finish.row = input.nextInt(); X.finish.col = input.nextInt(); X.pqbb(); } } }

Input & Output

8 8 3
3 3
4 5
6 6
2 1
7 7
11
2 1
3 1
4 1
5 1
6 1
7 1
7 2
7 3
7 4
7 5
7 6
7 7


17 17 77
1 1
1 2
1 3
1 5
1 8
1 15
1 17
2 1
2 6
2 7
3 1
4 4
4 13
4 14
4 15
5 2
5 3
5 7
5 9
5 16
6 5
6 8
6 11
7 4
7 14
7 17
8 7
8 12
8 17
9 6
9 9
9 11
9 12
9 13
9 16
10 7
10 9
10 13
10 15
11 3
11 5
11 7
11 13
11 15
12 4
12 5
12 6
12 12
12 14
12 15
12 17
13 7
13 10
13 11
14 2
14 3
14 8
15 3
15 8
15 10
15 11
15 12
15 13
15 14
15 15
15 17
16 4
16 6
16 12
16 17
17 1
17 8
17 11
17 12
17 13
17 16
17 17
5 14
15 9
15
5 14
6 14
6 13
7 13
7 12
7 11
8 11
8 10
9 10
10 10
11 10
12 10
12 9
13 9
14 9
15 9

Reference

王曉東《計算機演算法設計與分析》