布线问题(队列式分支限界)

计算机算法设计与分析(第5版)王晓东著 p178

0:电路板中可行的方格 1:障碍物 2:起点

是按课本上来的,初始起点设为2 是为了和 0,1进行区分
起点:1,1
终点: 4,6

1.path[] 数组是存放的起点到终点的路径方格
2.电路板最外面的一层全部赋值为1,表示围墙
3.数据结构是用的循环队列,循环队列中的最后一个位置是不存放值的,我这里的MAX是设的足够大,先进先出(FIFO)的方式满足队列式分支限界法
在这里插入图片描述

实现结果:
在这里插入图片描述
C代码:

//穷举+回溯 
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<malloc.h>

#define n 5		//方格行 
#define m 6 
typedef struct{		//方格 
	int row;		//行 
	int col;
}Position; 
#define MAX 100		//循环队列大小
typedef struct{
	Position *base;
	int front,rear;
}CqQueue; 
//初始化队列
void InitQueue(CqQueue &Q)
{		
	Q.base=(Position*)malloc(MAX*sizeof(Position));
	if(!Q.base)
		exit(0);
	Q.front=Q.rear=0;
}
//判断队列是否为空 
bool QueueEmpty(CqQueue Q)  
{
	if(Q.front==Q.rear) 
		return true; ///exit用于退出程序,return退出当前的函数 
	return false;             
}
//尾插队列
int EnQueue(CqQueue &Q,Position e)
{
	if((Q.rear+1)%MAX==Q.front) 
	 //牺牲了一个存储空间,此时数据存储到4位置,Q.rear此时等于5,即5位置没有数据 
		return 1;
	Q.base[Q.rear]=e;
	Q.rear=(Q.rear+1)%MAX;
}
//出队列 
void DeQueue(CqQueue &Q,Position &e)
{
	if(Q.rear==Q.front)
		exit(0);  // 队列为空 
	e=Q.base[Q.front]; 
	Q.front=(Q.front+1)%MAX;
}




//计算从起始位置start到目标位置finish的最短布线路径 
bool FindPath(Position &start,Position &finish,int PathLen,Position *path,CqQueue &Q){
	
	int grid[n+2][m+2];
	//初始化
	for(int i=0;i<n+2;i++){
		for(int j=0;j<m+2;j++){
			grid[i][j]=0;
		}
	}
	//障碍:
//	grid[3][6]=1; 
//	grid[4][5]=1;
	//设置方格阵列 “围墙 ”
	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;  //左边和右边 
	}
	//设初始点(1,1)和终点(4,6)
	start.row = 1;	start.col = 1;
	finish.row = 4; finish.col = 6;
	 
	//找到最短布线路径则返回true,否则返回false
	if((start.row == finish.row)&&(start.col == finish.col)){
		PathLen = 0;
		return true;
	} 

	//初始化相对位移
	Position offset[4];
	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;	//上
	int Numbrs = 4;			//相邻方格数
	
	Position here,nbr;
	here.row = start.row;		//目前的点为出发点的坐标 
	here.col = start.col;
	grid[start.row][start.col] = 2;
//	LinkedQueue<Position> Q;	//标记可达方格位置	改为队列 
	do{
		for(int i=0;i<Numbrs;i++){
			nbr.row = here.row+offset[i].row;
			nbr.col = here.col+offset[i].col;
			if(grid[nbr.row][nbr.col]==0){
				//该方格未标记
				grid[nbr.row][nbr.col] = grid[here.row][here.col]+1;	//当前方格的值+1 
				if((nbr.row==finish.row)&&(nbr.col==finish.col))
					break;		//完成布线
				EnQueue(Q,nbr); 			//把可行的方格加入队列,按右下左上的顺序依次加入 
				
			}
		}
		//是否到达目标位置finish
		if((nbr.row ==finish.row)&&(nbr.col==finish.col))
			break;
		//活结点队列是否非空
		if(QueueEmpty(Q))
			return false;	//无解
		DeQueue(Q,here);	//取下一个扩展结点
	}while(true);
	
	//构造最短布线路径
	PathLen = grid[finish.row][finish.col]-2;		//等于终点的值-2 
	printf("路径长度:%d\n",PathLen);
	path = new Position[PathLen];					//结构体数组? 
	//从目标位置finish开始向起始位置回溯
	here = finish; 
	for(int j=PathLen-1;j>=0;j--){
		path[j]=here;
		//找前驱位置
		for(int i=0;i<Numbrs;i++){
			nbr.row = here.row+offset[i].row;
			nbr.col = here.col+offset[i].col;
			if(grid[nbr.row][nbr.col]==j+2)
				break;
		}
		here = nbr;	//向前移动 	
	}
	printf("寻路路径如下:\n(%d,%d)\n",here.row,here.col);		//起点 
	for(int i=0;i<=PathLen-1;i++){
		printf("(%d,%d)\n",path[i].row,path[i].col);
	}
	
	printf("方格如下:\n");
	for(int i=0;i<n+2;i++){
		for(int j=0;j<m+2;j++){
			printf("%d  ",grid[i][j]);
		}
		printf("\n");
	}
	return true; 
} 


int main(){
	//队列 
	CqQueue Q;
	InitQueue(Q);	//初始化 
	
	//方格 
	Position start;		//起点 
	Position finish;	//终点 
	int pathlen;		//路径长度 
	Position *path;	//存放路径 
	FindPath(start,finish,pathlen,path,Q);
	return 0;
} 
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值