布线问题(分支限界法)

布线问题(分支限界法)一、首先说一下分支限界法的思想:(1)比较:分支限界法和回朔法有相似之处,但是回朔法是搜索问题的所有解,采用深度优先搜索;而分支限界法是搜索问题的最优解,采用的是广度优先搜索;(2)核心思想:分支

大家好,又见面了,我是你们的朋友全栈君。

一、首先说一下分支限界法的思想:

(1)比较:分支限界法和回朔法有相似之处,但是回朔法是搜索问题的所有解,采用深度优先搜索;而分支限界法是搜索问题的最优解,采用的是广度优先搜索

(2)核心思想:分支限界法中,每一个活节点都只有一次机会成为扩展节点。活节点一旦成为扩展节点,就一次性产生所有的儿子节点。在这些儿子节点中,导致不可行解或者导致非最优解的儿子节点被舍弃,其余儿子节点被加入活节点表中。此后,从活节点表中取下一节点成为当前扩展节点,并重复上述节点的扩展过程。这个过程一直在持续到找到所需要的最优解或者活节点表为空时为止;其中:选择扩展节点的方式可以分为:队列式分支限界法优先队列式分支限界法。后者相对于前者的改进是对活节点加入了优先级,优先级最高的成为扩展节点(通常通过最大堆最小堆实现);

二、布线问题描述:

<span role="heading" aria-level="2">布线问题(分支限界法)

<span role="heading" aria-level="2">布线问题(分支限界法)

代码如下:

//队列类 : LinkedQueue.h
#ifndef LINKEDQUEUE_H
#define LINKEDQUEUE_H

template <class Type>
class LinkedQueue{

public:
	LinkedQueue(){};

	explicit LinkedQueue(int Capacity);  //创建队列
	bool IsEmpty();  //判断是否空
	bool IsFull();  //判断是否满
	bool Add(Type &cell);  //向队列中加入元素
	bool Delete(Type &cell);  //删除队列中的元素

	~LinkedQueue();

private:
	Type cell;
	Type *ptr;  //队列中的元素指针
	int QueueLen;  //队列元素个数
	int QueueCapacity;  //队列容量
	int Head;
	int Tail;

};


template <class Type>
LinkedQueue<Type>::~LinkedQueue()
{
	delete[]ptr;
	ptr = nullptr;
}

template <class Type>
LinkedQueue<Type>::LinkedQueue(int Capacity)
{
	QueueCapacity = Capacity;
	Head = 0;
	Tail = 0;
	QueueLen = 0;
	ptr = new Type[QueueCapacity];
}

template <class Type>
bool LinkedQueue<Type>::IsEmpty()
{
	if (QueueLen == 0)
		return true;
	else
		return false;
}

template <class Type>
bool LinkedQueue<Type>::IsFull()
{
	if (QueueLen == QueueCapacity)
		return true;
	else
		return false;
}

template <class Type>
bool LinkedQueue<Type>::Add(Type &cell)
{
	if (IsFull())
		return false;
	else
	{
		ptr[Tail] = cell;
		Tail++;
		QueueLen++;
		return true;
	}
}

template <class Type>
bool LinkedQueue<Type>::Delete(Type &cell)
{
	if (IsEmpty())
		return false;
	else
	{
		cell = ptr[Head];
		Head++;
		QueueLen--;
		return true;
	}
}

#endif
//使用分支限界法解决布线问题main.cpp
//====================================================
#include <iostream>
#include "LinkedQueue.h"
//#include <queue>  

using namespace std;

int n, m;  //布线盘是n * m大小

class Position{
	public:
		int row;
		int col;
};

bool FindPath(int ** grid , Position start, Position finish, int &PathLen, Position * &path)
{
	//计算从起始位置start到目标位置finish的最短布线路径
	//找到最短布线路径则返回true,否则返回flase
	if ((start.row == finish.row) && (start.col == finish.col))
	{
		PathLen = 0;
		return true;
	}
	//设置方格阵列“围墙”
	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;  //左翼和右翼
	}
	//初始化相对位移
	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 neigh_num = 4;  //相邻方格数
	Position here, nbr;
	here.row = start.row;
	here.col = start.col;
	grid[start.row][start.col] = 2;
	//标记所有可以到达的方格位置

	LinkedQueue<Position> Q(n * m + 1);  //队列
	//queue<Position> Q();  //队列

	//标记可到达的相邻方格
	do {
		for (int i = 0; i < neigh_num; 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;
				if ((nbr.row == finish.row) && (nbr.col == finish.col))  //完成布线
					break;
				Q.Add(nbr);  //压入队列称为活节点
			}
		}
		//是否到达目标位置finish?
		if ((nbr.row == finish.row) && (nbr.col == finish.col))  //完成布线,是否要加这一步?
			break;
		//活节点队列是否非空
		if (Q.IsEmpty())  //无解
			return false;
		Q.Delete(here);  //取下一个扩展节点
	} while (true);
	//构造最短布线路径
	PathLen = grid[finish.row][finish.col] - 2;
	path = new Position[PathLen];
	//从目标位置finish开始向起始位置回溯
	here = finish;
	for (int j = PathLen - 1; j >= 0; j--)
	{
		path[j] = here;
		//找前驱位置
		for (int i = 0; i < neigh_num; 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;  //向前移动
	}
	return true;
}

int main(void)
{
	Position start, finish;  //开始位置和目标位置
	int PathLen;  //最短路径的长度
	Position *path;  //记录的最短路径
	cout << "请输入布线盘的大小,n * m 规格: " << endl;
	cin >> n >> m;
	cout << "请输入开始位置(x , y) :" << endl;
	cin >> start.col >> start.row;
	cout << "请输入结束位置(x , y) :" << endl;
	cin >> finish.col >> finish.row;

	int ** grid = new int*[n + 2];
	for (int i = 0; i < n + 2; i++)
	{
		grid[i] = new int[m + 2];
	}
	for (int i = 0; i < n + 2; i++)
	{
		for (int j = 0; j < m + 2; j++)
		{
			grid[i][j] = 0;
		}
	}

	FindPath(grid, start, finish, PathLen, path);

	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= m; j++)
		{
			cout << grid[i][j] << "  ";
		}
		cout << endl;
	}

	cout << "最短路径是: " << endl;
	cout << PathLen << endl;

	system("pause");
	return 0;
}

效果图类似:

<span role="heading" aria-level="2">布线问题(分支限界法)

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/155186.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • python一维数组转置_python矩阵转置[通俗易懂]

    python一维数组转置_python矩阵转置[通俗易懂]python中的矩阵转置首先,数据应该是np.asarray型,然后,使用numpy.transpose来操作。transpose方法只能处理高维数组(>1),如果处理一维数组会报错;对于二维数组:data1=np.arange(4).reshape((2,2))print(data1)>>[[01][23]]data1=np.transpose(data1)print(data1)>…

    2022年5月5日
    209
  • zookeeper入门教程_日语入门自学

    zookeeper入门教程_日语入门自学zookeeperwatcher架构zookeeper 配置中心分布式ID分布式锁集群搭建数据一致性协议:zab协议Zookeeper Leader选举Observer角色及其配置watcher架构客户端首先将Watcher注册到服务器,同时将Watch对象保存到客户端的Watch管理器中。当Zookeeper服务器监听到的数据发生变化时,服务器会通知客户端,接着客户端的Watch管理器会触发相关的Watcher来回调响应处理逻辑,从而完成整体的数据发布/订阅流程。javaAPIJava

    2022年8月8日
    3
  • listview嵌套GridView_react grid layout

    listview嵌套GridView_react grid layoutGridView嵌套GridView,对子GridView及父GridView级联删除的问题http://blog.csdn.net/amandag/archive/2007/05/31/1633395.aspx利用GridView显示主细表并添加删除、打开、关闭功能(续)http://dotnet.aspx.cc/article/f73eeaa9-2bdc-47fd-a…

    2022年10月7日
    0
  • VMware中的ubuntu虚拟机开机黑屏,无法打开桌面

    昨天因为在虚拟机中搭环境,崩了,可能是因为脚本错误什么的原因,或者误删除了什么东西的原因,导致,虚拟机重启之后一直处于黑屏状态。如下图:然后百度了很多解决方法,都不成功,后来有大佬指点用快照恢复,但是,我发现一个残酷的事实,我之前没有使用过快照,所以不可行,所以只好重装了。信任IT界名言“没有什么是重装系统解决不了的”。可能只是我的这个不行,但是整理了一下网上的方法,码文,纪念一下…

    2022年4月6日
    1.1K
  • pycharm2021host激活码【在线注册码/序列号/破解码】「建议收藏」

    pycharm2021host激活码【在线注册码/序列号/破解码】,https://javaforall.net/100143.html。详细ieda激活码不妨到全栈程序员必看教程网一起来了解一下吧!

    2022年3月19日
    58
  • 电脑怎么连接信捷plc_信捷plc怎么连接电脑

    电脑怎么连接信捷plc_信捷plc怎么连接电脑1、 以XC系列为例,需要专用的信捷PLC下载线2、 打开PLC编程软件,把串口线连接PC和PLC。,并查看端口:我的电脑—》设备管理—》串口(端口),以端口5为例3、 连接PLC:选项—》软件串口设置,选择实际的串口,默认是modbus通信,点击检测,会自动搜索波特率校验位之类的,直到找到和PLC配置相同参数说明连接成功…

    2022年10月9日
    0

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号