IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> PREV-144 卡片换位【第七届】【省赛】【C组】——bfs问题 -> 正文阅读

[数据结构与算法]PREV-144 卡片换位【第七届】【省赛】【C组】——bfs问题

你玩过华容道的游戏吗?
这是个类似的,但更简单的游戏。
看下面 3 x 2 的格子

±–±--±–+
| A | * | * |
±–±--±–+
| B | | * |
±–±--±–+
在其中放5张牌,其中A代表关羽,B代表张飞,* 代表士兵。
还有一个格子是空着的。
你可以把一张牌移动到相邻的空格中去(对角不算相邻)。
游戏的目标是:关羽和张飞交换位置,其它的牌随便在哪里都可以。

输入格式

输入两行6个字符表示当前的局面

输出格式

一个整数,表示最少多少步,才能把AB换位(其它牌位置随意)

输入样例

在提交之后,系统测试系统给我爆出了有一个测试用例不通过,我打开看了一下,发现是这个测试用例的错误。它的测试用例是没有给空格,而题目中说有一个格子是空着的。这就是那个测试用例:

*A*
*B*

而正确的应该是:

*A
*B*

输出样例

10

代码

在这道题目中,难点就是在二维数组向着不同方向转化时,怎么去记录二维数组的情况。
还有,这道题只要求A和B的位置实现互换,不考虑其他牌的情况。

#include <iostream>
#include <stdio.h>
#include <map>
#include <string>
#include <queue>

using namespace std;

struct Node
{
	int x;    // 记录空格所在的行 
	int y;    //记录空格所在的列 
	int ax;   //记录A所在的行 
	int ay;   //记录A所在的列 
	int bx;   //记录B所在的行 
	int by;   //记录B所在的行 
	int step; //记录广搜的步数,依据此输出到达目标所走的步数 
	string s; //将二维数组转化为字符串,记录每一次广搜时二维数组的变化 
};
char str[2][3];   //定义二位字符数组 
int Ax,Ay,Bx,By,spaceX,spaceY;  //Ax,Ay,Bx,By记录在键入二维数组时A,B所在的行和列
								//spaceX,spaceY记录在键入二维数组时空格所在的行和列 
int dir[4][2] = { {-1,0},{1,0},{0,-1},{0,1} };   //定义四个方向,在二维数组中,空格可以上下左右去移动 
map<string, bool> mp;   //定义一个map,记录二维数组转化的字符串,防止有重复的情况出现
                        //这道题不同于其他的广搜题目,这个只能根据空格去移动,
						//并且我们要去将二维数组的每一个变化能够去记录
						//而在每一步的广搜时,不同方向上的二维数组的变化是不同的 

void bfs()
{
	//定义一个开始结点,初始化节点 
	Node start;
	start.x = spaceX;
	start.y = spaceY;
	start.ax = Ax;
	start.ay = Ay;
	start.bx = Bx;
	start.by = By;
	start.step = 0;
	for(int i=0;i<2;i++)
	{
		for(int j=0;j<3;j++)
		{
			start.s += str[i][j];
		}
	}
	
	//定义一个队列,将开始结点放入 
	queue<Node> q;
	q.push(start);
	//标记键入的二维数组转化为的字符串为true,代表这个情况已经出现 
	mp[start.s] = true;
	
	while(!q.empty())
	{
		//取出队首元素 
		Node now = q.front();
		q.pop();
		
		int step = now.step;
		//在空格节点移动的过程中,假如与A或者B发生交换
		//那么就改变相应的ax,ay或者bx,by的改变
		//本题要求的是,最后不考虑其他的影响,
		//只考虑相较于最开始的情况,在ax,ay或者bx,by的改变后,最后A和B是否完成位置上的互换 
		if(now.bx == Ax && now.by == Ay &&
		   now.ax == Bx && now.ay == By)
		{
	   		cout<<step<<endl;
	   		return;
		}
		
		//将结点字符串转化为二维数组 
		char Str[2][3];
		int count = 0;
		for (int i = 0; i < 2; i++)
		{
			for (int j = 0; j < 3; j++)
			{
				Str[i][j] = now.s[count];
				count++;
			}
		}
		
		//在空格所在的位置,沿着四个方向进行广搜 
		for(int i=0;i<4;i++)
		{
			//因为根据一个二维数组向四个方向进行广搜,得到的结果不一样
			//而这四个方向的广搜又都是基于这一个Str二维数组
			//因此在方向变化时,我们要定义一个辅助数组helpStr回到Str这个二维数组,再向下一个方向去延伸 
			char helpStr[2][3];
			for (int row = 0; row < 2; row++)
			{
				for (int col = 0; col < 3; col++)
				{
					helpStr[row][col] = Str[row][col];
				}
			}
			
			Node next;
			next.x = now.x + dir[i][0];
			next.y = now.y + dir[i][1];
			
			//判断变化后的空格的位置是否在数组范围之内 
			if(next.x>=0 && next.x<2 &&
			   next.y>=0 && next.y<3)
			{
				//如果空格即将到达的位置上是'*',交换两者的元素
				//此时A和B的位置没有发生变化,就继承上一个结点的A和B的位置,步数加一
			   	if(helpStr[next.x][next.y] == '*')
			   	{
			   	   char tmp = helpStr[next.x][next.y];
			   	   helpStr[next.x][next.y] = helpStr[now.x][now.y];
			   	   helpStr[now.x][now.y] = tmp;
			   	   
			   	   next.ax = now.ax;
			   	   next.ay = now.ay;
			   	   next.bx = now.bx;
			   	   next.by = now.by;
			   	   next.step = now.step+1;
			   	}
			   	//如果空格即将到达的位置上是'A',交换两者的元素
				//此时A的位置发生变化,即此时'A'要去往空格所在位置,即上一个结点的空格位置就为A新的位置 
				//而B的位置未发生变化,就继承上一个节点的B的位置,步数加一 
			   	if(helpStr[next.x][next.y] == 'A')
			   	{
			   	   char tmp = helpStr[next.x][next.y];
			   	   helpStr[next.x][next.y] = helpStr[now.x][now.y];
			   	   helpStr[now.x][now.y] = tmp;
			   	   
			   	   next.ax = now.x;
			   	   next.ay = now.y;
			   	   next.bx = now.bx;
			   	   next.by = now.by;
			   	   next.step = now.step+1;
			   	}
			    //如果空格即将到达的位置上是'B',交换两者的元素
				//此时B的位置发生变化,即此时'B'要去往空格所在位置,即上一个结点的空格位置就为B新的位置 
				//而A的位置未发生变化,就继承上一个节点的B的位置,步数加一
			   	if(helpStr[next.x][next.y] == 'B')
			   	{
			   	   char tmp = helpStr[next.x][next.y];
			   	   helpStr[next.x][next.y] = helpStr[now.x][now.y];
			   	   helpStr[now.x][now.y] = tmp;
			   	   
			   	   next.bx = now.x;
			   	   next.by = now.y;
			   	   next.ax = now.ax;
			   	   next.ay = now.ay;
			   	   next.step = now.step+1;
			   	}
			   	
			   	//将二维数组转化为字符串 
			   	string news = "";
			   	for (int i = 0; i < 2; i++)
				{
					for (int j = 0; j < 3; j++)
					{
						news += helpStr[i][j];
					}
				}
				
				//判断这个字符串的情况是否出现过 
				if(!mp[news])
				{
					mp[news] = true;
					next.s = news;
					q.push(next);  //没有出现过,就放到map中,并标记出现了,放到队列中 
				}
			}
		}
	}
}

int main()
{
	//键入二维数组 
	for(int i=0; i<2; i++)
	{
		gets(str[i]);
	}
	
	//找寻第一次时A,B和空格所在的位置 
	for(int i=0;i<2;i++)
	{
		for(int j=0;j<3;j++)
		{
			if(str[i][j] == 'A')
			{
				Ax = i;
				Ay = j;
			}
			if(str[i][j] == 'B')
			{
				Bx = i;
				By = j;
			}
			if(str[i][j] == ' ')
			{
				spaceX = i;
				spaceY = j;
			}
		}
	}
	
	bfs();
	
	return 0;
}
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-03-08 22:48:16  更:2022-03-08 22:50:07 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 13:55:42-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码