布线问题(分支限界法)

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

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

(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;
}

效果图类似:

原文地址:https://www.cnblogs.com/zf-blog/p/9043549.html

时间: 2024-11-12 01:31:34

布线问题(分支限界法)的相关文章

转:算法分析之 五大常用算法

算法分析之 五大常用算法 算法的复杂度 1.分治法 · 话说递归与HANOI塔 · 二分法求方程近似解 · 用C++实现合并排序 · 求最大值和最小值的分治算法 2.动态规划法 · 动态规划求0/1背包问题 · 最长公共子串问题的实现 · 用动态规划实现导弹拦截 · 最大化投资回报问题的实现 3.贪心算法 · 最小生成树之Prim算法 · 最小生成树之kruskal算法 · 贪心算法在背包中的应用 · 汽车加油问题之贪心算法 4.回溯法 · 回溯法之数的划分 · 回溯法求解运动员最佳配对问题 ·

LSI设计(4)FOCR快速最优通道布线

 [email protected]   [摘要]本文提出的快速最优通道布线算法FOCR(Fast Optimal Channel Router)是Kernighan-shweikert-Persky 最优通道布线算法[2]和wada的改进布线算法[4]的改进.这些算法的"最优性"意义完全相同,但新算法的执行速度统计地比上述二种法远远为快. 1.引 言  通道布线算法是大规模集成电路(LSI)和印刷电路板(PCB)布线设计中广泛应用的一类算法,其特点是采用并行布线方式,因而与串行布线的

算法复习笔记(回溯法,分支限界法)

回溯法 分支限界法 回溯法 回溯法(探索与回溯法)是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标.但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法. 基本思想: 在包含问题的所有解的解空间树中,按照深度优先搜索的策略,从根结点出发深度探索解空间树.当探索到某一结点时,要先判断该结点是否包含问题的解,如果包含,就从该结点出发继续探索下去,如果该结点不包含问题的解,则逐层向其祖先结点回溯.(其实回溯法就是对隐式图的深度优先搜索

分支限界法

一.分支限界法的基本思想 在扩展结点处,先生成其所有的儿子结点(分支),然后再从当前的活结点表中选择下一个扩展结点.为了有效地选择下一扩展结点,加速搜索的进程,在每一活结点处,计算一个函数值(限界),并根据函数值,从当前活结点表中选择一个最有利的结点作为扩展结点,使搜索朝着解空间上有最优解的分支推进,以使尽快找出一个最优解. (1)活结点:如果已生成一个结点而它的所有儿子结点还没有全部生成,则这个结点叫做活结点. (2)扩展结点:当前正在生成其儿子结点的活结点叫扩展结点(正扩展的结点). (3)

PCB布线技巧

在进行布线之前,首选需要了解一下电路图,比如那些是信号线,那些电容有什么作用.电源需要走多宽. 1mm = 40ml 一般情况下1A的电流线宽选择1mm 最好将信号线表不同的颜色做特殊处理,保证信号的传输完整.走线的时候打开DRP走线,F4是打孔. 一般规则设置为5ml以上. 当移动原件的时候需要看线的走向可以如下图设置. 在布线的时候需要打孔设置过孔方法如下. 弹出如下对话框

最小生成树 之 CODE[VS] 1231 最优布线问题

/* 最小生成树 之 CODE[VS] 1231 最优布线问题 Kruskal算法(邻接表) */ 1 #include <iostream> 2 #include <cstdlib> 3 #include <cstdio> 4 #include <cstddef> 5 #include <iterator> 6 #include <algorithm> 7 #include <string> 8 #include <

布线问题(prime)

布线问题 时间限制:1000 ms  |  内存限制:65535 KB 难度:4 描述 南阳理工学院要进行用电线路改造,现在校长要求设计师设计出一种布线方式,该布线方式需要满足以下条件:1.把所有的楼都供上电.2.所用电线花费最少 输入 第一行是一个整数n表示有n组测试数据.(n<5)每组测试数据的第一行是两个整数v,e.v表示学校里楼的总个数(v<=500)随后的e行里,每行有三个整数a,b,c表示a与b之间如果建铺设线路花费为c(c<=100).(哪两栋楼间如果没有指明花费,则表示这

nyist oj 38 布线问题 (最小生成树 prim)

布线问题 时间限制:1000 ms  |  内存限制:65535 KB 难度:4 描述 南阳理工学院要进行用电线路改造,现在校长要求设计师设计出一种布线方式,该布线方式需要满足以下条件: 1.把所有的楼都供上电. 2.所用电线花费最少 输入 第一行是一个整数n表示有n组测试数据.(n<5) 每组测试数据的第一行是两个整数v,e. v表示学校里楼的总个数(v<=500) 随后的e行里,每行有三个整数a,b,c表示a与b之间如果建铺设线路花费为c(c<=100).(哪两栋楼间如果没有指明花费

1231 最优布线问题

1231 最优布线问题 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 白银 Silver 题目描述 Description 学校需要将n台计算机连接起来,不同的2台计算机之间的连接费用可能是不同的.为了节省费用,我们考虑采用间接数据传输结束,就是一台计算机可以间接地通过其他计算机实现和另外一台计算机连接. 为了使得任意两台计算机之间都是连通的(不管是直接还是间接的),需要在若干台计算机之间用网线直接连接,现在想使得总的连接费用最省,让你编程计算这个最小的费用. 输入描述 In