算法设计与分析: 6-18 一般解空间的优先队列式分支限界法

6-18 一般解空间的优先队列式分支限界法

问题描述

试设计一个用优先队列式分支限界法搜索一般解空间的函数。该函数的参数包括结点可 行性判定函数和上界函数等必要的函数,并将此函数用于解布线问题。
印刷电路板将布线区域划分成 n×m 个方格阵列如图(a)所示。精确的电路布线问题要求 确定连接方格 a 的中点到方格 b 的中点的最短布线方案。在布线时,电路只能沿直线或直角布线,如图(b)所示。为了避免线路相交,已布了线的方格做了封锁标记,其它线路不允许穿过被封锁的方格。

《算法设计与分析: 6-18 一般解空间的优先队列式分支限界法》

对于给定的布线区域,编程计算最短布线方案。

数据输入:
第一行有 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

王晓东《计算机算法设计与分析》

    原文作者:分支限界法
    原文地址: https://blog.csdn.net/IOIO_/article/details/81192405
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞