算法设计与分析: 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

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

这是一个典型的最短路径问题,可以使用 Dijkstra 算法或 A* 算法决。以下是使用 Dijkstra 算法求的 C++ 实现: ```c++ #include <iostream> #include <queue> #include <cstring> using namespace std; const int MAXN = 105; const int INF = 0x3f3f3f3f; int n, m; int sx, sy, tx, ty; // 起点和终点坐标 int graph[MAXN][MAXN]; // 图的邻接矩阵 int dis[MAXN][MAXN]; // 起点到每个点的最短距离 bool vis[MAXN][MAXN]; // 该点是否已被访问过 struct Node { int x, y, dis; bool operator < (const Node& other) const { return dis > other.dis; // 优先队列使用大根堆 } }; bool isInBound(int x, int y) { return x >= 1 && x <= n && y >= 1 && y <= m; } void dijkstra() { memset(dis, INF, sizeof(dis)); memset(vis, false, sizeof(vis)); priority_queue<Node> q; q.push({sx, sy, 0}); dis[sx][sy] = 0; while (!q.empty()) { Node cur = q.top(); q.pop(); if (vis[cur.x][cur.y]) continue; vis[cur.x][cur.y] = true; // 更新周围节点的最短距离 for (int i = -1; i <= 1; i++) { for (int j = -1; j <= 1; j++) { if (i == 0 && j == 0) continue; // 自身不算 if (i != 0 && j != 0) continue; // 只能直线或直角布线 int nx = cur.x + i, ny = cur.y + j; if (!isInBound(nx, ny)) continue; // 超出边界 if (graph[nx][ny] == 1) continue; // 被封锁 int ndis = cur.dis + abs(i) + abs(j); if (ndis < dis[nx][ny]) { dis[nx][ny] = ndis; q.push({nx, ny, ndis}); } } } } } int main() { cin >> n >> m; cin >> sx >> sy >> tx >> ty; // 读入图的邻接矩阵 for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { cin >> graph[i][j]; } } dijkstra(); cout << dis[tx][ty] << endl; return 0; } ``` 其中,`isInBound` 函数用于判断该点是否超出边界,`dijkstra` 函数用于求最短路径,`Node` 结构体用于存储节点的坐标和起点到该点的最短距离。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值