西南交大算法实验8.3-机器人推箱子

该代码实现了一个算法,通过分支限界法和回溯法来确定机器人推动箱子达到目标位置所需的最少移动次数。程序首先使用广度优先搜索获取可能的箱子移动方向,然后通过回溯法判断机器人路径的有效性,同时避免机器人绕圈。最终找到最优解并输出最小移动次数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

做完8.4当然就顺便看看8.3,这个题的实验要求是求得箱子最少的移动次数,因此难点在箱子的移动方向,以及回溯法让机器人到达能推动箱子的坐标。

 

--------------------------------------------------------------------------------------------------------------------

以下是代码实现,采用分支限界法实现该实验,广度搜索得到箱子能移动的方向,然后利用回溯法深度遍历地图判断机器人能否让箱子移动。

-----------------------------------------------------------------------------------------------------------------------------

#include<iostream>
using namespace std;
int row, col;
int INI_BX, INI_BY;//开始时箱子坐标
int INI_TX, INI_TY;//终点
int SX, SY;//机器人
struct heapnode {
	int length;//距离终点的距离
	int level;//移动的步数
	int route[100];//route中的值为0,1,2,3,4,其中0为初始化,1-4代表朝着上下左右移动
	int x, y;//route[level]箱子的坐标,方便找位置
};
heapnode heap[100];
int heaplength = 0;
int minlevel = 1e9;//最小移动次数

//小顶堆
void Insert(heapnode temp) {
	int i = 0;
	for (i = heaplength + 1; i > 1; i/=2) {
		if (temp.length >= heap[i / 2].length)break;
		else heap[i] = heap[i / 2];
	}
	heap[i] = temp;
	heaplength++;
}

void Delete() {
	heapnode temp = heap[heaplength];
	heap[1] = heap[heaplength];
	int i;
	heap[heaplength].length = 1e9;
	for (i = 2; i < heaplength; i*=2) {
		if (heap[i].length > heap[i + 1].length)i++;
		if (heap[i].length >= temp.length)break;
		heap[i / 2] = heap[i];
	}
	heap[i / 2] = temp;
	heaplength--;
}

//避免出现浮点数,因此不做根号处理
int GetLen(heapnode temp) {
	return ((temp.x - INI_TX) * (temp.x - INI_TX) + (temp.y - INI_TY)* (temp.y - INI_TY));
}
int spath[100][100];//机器人走过的路
//判断机器人是否在绕圈
bool Road(int x, int y) {
	if (spath[x][y] == 1) return 0;
	return 1;
}

//回溯法让机器人移动到该位置
bool dfs(char **map,int x,int y,heapnode temp) {
	//可优化,但懒得改了,这个地方是得到一个tmap地图,将map地图中当前的箱子位置视为障碍物'#'
	char** tmap = new char* [row];
	for (int i = 0; i < row; i++) tmap[i] = new char[col];
	for (int i = 0; i < row; i++) {
		for (int j = 0; j < col; j++) 
			tmap[i][j] = map[i][j];
	}
	tmap[temp.x][temp.y] = '#';//将箱子视为路障
	bool is = 0;

	if (SX == x && SY == y) return true;
	else {

		//上
		if (tmap[SX - 1][SY] != '#' && Road(SX-1,SY) && !is) {

			spath[SX][SY]=1;
			SX = SX - 1;
			is = dfs(map,x,y,temp);
			SX = SX + 1;
			spath[SX][SY] = 0;
		}
		//下
		if (tmap[SX + 1][SY] != '#' && Road(SX + 1, SY) && !is) {

			spath[SX][SY] = 1;
			SX = SX + 1;
			is = dfs(map, x, y, temp);
			SX = SX - 1;
			spath[SX][SY] = 0;
		}
		//左
		if (tmap[SX][SY - 1] != '#' && Road(SX, SY - 1) && !is) {

			spath[SX][SY] = 1;
			SY = SY - 1;
			is = dfs(map, x, y, temp);
			SY = SY + 1;
			spath[SX][SY] = 0;
		}
		//右
		if (tmap[SX][SY + 1] != '#' && Road(SX, SY + 1) && !is) {

			spath[SX][SY] = 1;
			SY = SY + 1;
			is = dfs(map, x, y, temp);
			SY = SY - 1;
			spath[SX][SY] = 0;
		}


	}

	return is;
}
//判断机器人能否支持该移动
bool Robot(char **map,int x,int y,heapnode temp) {
	if (map[x][y] == '#') return false;
	else if (dfs(map, x, y, temp)) return true;
	return false;
}


void GetAns(char **map) {
	heapnode rootnode;
	rootnode.level = 0;
	rootnode.x = INI_BX;
	rootnode.y = INI_BY;
	rootnode.length = GetLen(rootnode);
	rootnode.route[0] = 0;
	Insert(rootnode);
	while (heaplength>0) {	
		heapnode temp = heap[1];
		Delete();
		if (temp.length == 0) {
			if (minlevel > temp.level)  minlevel = temp.level;
		}
		else {
			//推箱子往上
			if (map[temp.x - 1][temp.y] != '#' && Robot(map, temp.x + 1, temp.y, temp)) {
				heapnode node;
				node.x = temp.x - 1;
				node.y = temp.y;
				node.length = GetLen(node);
				node.level = temp.level + 1;
				for (int i = 0; i <= temp.level; i++) {
					node.route[i] = temp.route[i];
				}
				node.route[temp.level + 1] = 1;//上为1
				if(node.level < minlevel)//进行限界,若移动次数比当前求得的最优解minlevel大,则标记为废节点
				Insert(node);
			}

			//推箱子往下
			if (map[temp.x + 1][temp.y] != '#' && Robot(map, temp.x - 1, temp.y, temp)) {
				heapnode node;
				node.x = temp.x + 1;
				node.y = temp.y;
				node.length = GetLen(node);
				node.level = temp.level + 1;
				for (int i = 0; i <= temp.level; i++) {
					node.route[i] = temp.route[i];
				}
				node.route[temp.level + 1] = 2;//下为2
				if (node.level < minlevel)
				Insert(node);
			}
			//推箱子往左
			if (map[temp.x][temp.y - 1] != '#' && Robot(map, temp.x, temp.y + 1, temp)) {
				heapnode node;
				node.x = temp.x;
				node.y = temp.y - 1;
				node.length = GetLen(node);
				node.level = temp.level + 1;
				for (int i = 0; i <= temp.level; i++) {
					node.route[i] = temp.route[i];
				}
				node.route[temp.level + 1] = 3;//左为3
				if (node.level < minlevel)
				Insert(node);
			}
			//推箱子往右
			if (map[temp.x][temp.y + 1] != '#' && Robot(map, temp.x, temp.y - 1, temp)) {
				heapnode node;
				node.x = temp.x;
				node.y = temp.y + 1;
				node.length = GetLen(node);
				node.level = temp.level + 1;
				for (int i = 0; i <= temp.level; i++) {
					node.route[i] = temp.route[i];
				}
				node.route[temp.level + 1] = 4;//右为4
				if (node.level < minlevel)
				Insert(node);
			}

		}

	}
}

int main() {
	cin >> row >> col;
	char** map = new char* [row];
	for (int i = 0; i < row; i++) map[i] = new char[col];

	for (int i = 0; i < row; i++) {
		for (int j = 0; j < col; j++) {
			cin >> map[i][j];
			if (map[i][j] == 'T') {
				INI_TX = i;
				INI_TY = j;
			}
			if (map[i][j] == 'S') {
				SX = i;
				SY = j;
			}
			if (map[i][j] == 'B') {
				map[i][j] = '.';
				INI_BX = i;
				INI_BY = j;
			}
		}
	}
	GetAns(map);
	//for (int i = 0; i < row; i++) {
	//	for (int j = 0; j < col; j++) {
	//		cout << map[i][j] ;
	//	}
	//	cout << endl;
	//}
	cout << minlevel;
	return 0;
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值