蓝桥杯BFS 移动方格的问题

本文详细解析了蓝桥杯竞赛中的移动方块问题,利用BFS搜索算法求解从初始状态出发能否达到目标状态。介绍了算法的具体实现过程,并提供了完整的C++代码示例。

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

              这道题好像是某一届高职高专的最后一题,原题如下:
/*
10. 移动字母
2x3=6个方格中放入ABCDE五个字母,右下角的那个格空着。如图1所示。
和空格子相邻的格子中的字母可以移动到空格中,比如,图中的C和E就可以移动,移动后的局面分别是:
A B  
D E C

A B C
D E

  为了表示方便,我们把6个格子中字母配置用一个串表示出来,比如上边的两种局面分别表示为:
AB*DEC
ABCD*E
  题目的要求是:请编写程序,由用户输入若干表示局面的串,程序通过计算,输出是否能通过对初始状态经过若干次移动到达该状态。可以实现输出1,否则输出0。初始状态为:ABCDE*
  用户输入的格式是:先是一个整数n,表示接下来有n行状态。程序输出也应该是n行1或0
  例如,用户输入:
3
ABCDE*
AB*DEC
CAED*B

  则程序应该输出:
1
1
0
*/

解题思路分析:  根据题目分析可知,每次能否移动某个方格的关键就是* 的位置,根据*的不同位置有不同的移动方法,而且每次移动可能都能有新的状态产生,当然可能会重复,由于每次都只能和* 相邻的位置元素交换而且要避免和前面的已经有过的状态重复,所以我当时拿到题目使用的是BFS搜索,我的思路是这样的:

                首先我有一个队列,(char queue[710][6];  // 定义一个队列  总共排列710 总不可能超过710总情况),初始时放入ABCDE*   开始队列下标index指向初始情况队列总数countqueue=1如图:

开始的排列:

所以可以将2号和5号对换  得到  AB*DEC (没有出现过,入队列),也可以将4号和5号兑换  得到ABCD*E(没有出现 ,入队列)

此时队列的情况:

经过一次变化之后index加1   countqueue=3指向AB*DEC

此时可以将1,2   或则 2,5对换分别得到A*BDEC(没出现,入队列)  和 ABCDE*(重复,舍去)此次操作之后队列的index为2,countqueue=4:,如下图:


按照此步奏不断的重复 知道 index>=countqueue循环截止

程序代码如下(打印出所有可能移到的结果):

#include <cstdlib>
#include <iostream>
#include<algorithm>
//  蓝桥杯移动方格的问题 
using namespace std;
char queue[710][6];  // 定义一个队列
 int countqueue;  // 记录队列的长度 
int getIndex(char *a)  // 找到* 的下标
{   int result=0;
    for(int i=0;i<6;i++)
		if(a[i]=='*')					
		{
		    result=i;
			break;             						 
		}
    return result;                   
} 
bool equals(char *a,char *b)  // 判断两个字符串是否相等 
{
     bool sign=true;
     for(int i=0;i<6;i++)
         if(a[i]!=b[i])
         {
			sign=false;
			break;															
          } 
    return sign;
 }
 bool inQueue(char *a)  // 判断字符串是否存在队列中
 {
	bool sign=false;  // 不存在 
	for(int i=0;i<countqueue;i++)
		if(equals(a,queue[i]))
		{ 
			sign=true;  // 存在
			break;
		}
	return sign; 
} 
 void pushqueue(char *a)  // 进队列 
 {
	for(int i=0;i<6;i++)
		queue[countqueue][i]=a[i];
	countqueue++;	
} 
char* swap(char* a,int m,int n) // 将m,n 下标的字符对换 
{
	char* result=new char[6];
	for(int i=0;i<6;i++)
		result[i]=a[i];
	char t=result[m];
	result[m]=result[n];
	result[n]=t;
	return result; 
}

void getAllPerm()  // 得到所有的排列 
{
	int i=0;
	while(i<countqueue)
	{
		int index=getIndex(queue[i]);  // 得到当前串中* 的下标
		char* swapchar;  // 通过交换得到的字符串 
		switch(index)   //  根据* 号的下标  进行字符串的交换 
		{	
			
			case 0:	swapchar=swap(queue[i],0,1);
					if(!inQueue(swapchar))  // 如果字符串不在队列中,则加入到队列中 
						pushqueue(swapchar);
					swapchar=swap(queue[i],0,3);
					if(!inQueue(swapchar))
						pushqueue(swapchar);
					break;   //  错误 原因 
			case 1: swapchar=swap(queue[i],0,1);
				
					if(!inQueue(swapchar))
						pushqueue(swapchar);
					swapchar=swap(queue[i],2,1);
					if(!inQueue(swapchar))
						pushqueue(swapchar);
					swapchar=swap(queue[i],4,1);
					if(!inQueue(swapchar))
						pushqueue(swapchar);
					break;   //  错误 原因 
			case 2:	
					swapchar=swap(queue[i],2,1);
					if(!inQueue(swapchar))
						pushqueue(swapchar);
					swapchar=swap(queue[i],2,5);
					if(!inQueue(swapchar))
						pushqueue(swapchar);
					break;   //  错误 原因 
			case 3:	swapchar=swap(queue[i],3,0);
					if(!inQueue(swapchar))
						pushqueue(swapchar);
					swapchar=swap(queue[i],3,4);
					if(!inQueue(swapchar))
						pushqueue(swapchar);
					break;   //  错误 原因 
			case 4: swapchar=swap(queue[i],4,1);
					if(!inQueue(swapchar))
						pushqueue(swapchar);
					swapchar=swap(queue[i],4,3);
					if(!inQueue(swapchar))
						pushqueue(swapchar);
					swapchar=swap(queue[i],4,5);
					if(!inQueue(swapchar))
						pushqueue(swapchar);
					break;   //  错误 原因 
			case 5:	swapchar=swap(queue[i],5,4);
					if(!inQueue(swapchar))
						pushqueue(swapchar);
					swapchar=swap(queue[i],5,2);
					if(!inQueue(swapchar))
						pushqueue(swapchar);
					break;   //  错误 原因 
		} 
		i++;
	} 
} 
int main(int argc, char *argv[])
{
    int n;
   	char a[7]="abcde*";
   	pushqueue(a);
   	getAllPerm();
   	cout<<"print: queue"<<endl;
	for(int i=0;i<countqueue;i++)
	{
		for(int j=0;j<6;j++)
			cout<<queue[i][j]<<"  ";
		cout<<endl;
	}
   cout<<"共有"<<countqueue<<"条合格的记录"<<endl; 
    cin>>n;
    int *result=new int[n];
    for(int i=0;i<n;i++)
    {
		char test[6];
		fflush(stdin);
		for(int j=0;j<6;j++)
			cin>>test[j];
		if(inQueue(test))
			result[i]=1;
		else
			result[i]=0;	
	}
	for(int i=0;i<n;i++)
	{
		cout<<result[i]<<endl;
	}

	
	
	/* 
	cout<<"print: queue"<<endl;
	for(int i=0;i<countqueue;i++)
	{
		for(int j=0;j<6;j++)
			cout<<queue[i][j]<<"  ";
	
		cout<<endl;
	}*/
	system("pause");
    return EXIT_SUCCESS;
}



### 关于蓝桥杯竞赛中的广度优先搜索(BFS) 在蓝桥杯竞赛中,广度优先搜索(BFS)是一种常用的方法用于解决最短路径问题。它通过逐层扩展的方式探索图结构,能够有效地找到从起始点到目标点的最短路径[^1]。 以下是基于 Python 的 BFS 实现方法及其解题思路: #### 解题思路 为了实现 BFS 来解决问题,通常需要以下几个核心部分: - **队列**:用来存储当前正在处理的节点以及其相关信息。 - **标记数组/集合**:防止重复访问已经遍历过的节点,从而提高效率并避免死循环。 - **距离记录**:保存每个节点到起点的距离信息,以便最终返回最短路径长度。 具体来说,可以通过以下方式构建解决方案: - 初始化一个队列并将初始状态加入其中; - 使用 while 循环不断取出队首元素进行分析直到达到目的地为止; - 对每一个弹出的状态尝试所有可行的操作,并把新产生的合法状态推入队尾继续考察; 下面给出一段通用版本的 Python 代码示例来展示如何利用 BFS 寻找迷宫类题目中最短行走步数的情况。 #### 示例代码 ```python from collections import deque def bfs(start, end, grid): rows, cols = len(grid), len(grid[0]) # Directions array representing possible moves (up, down, left, right). directions = [(-1, 0), (1, 0), (0, -1), (0, 1)] visited = [[False]*cols for _ in range(rows)] # Visited matrix. queue = deque([(start[0], start[1], 0)]) # Queue with initial position and distance. while queue: x, y, dist = queue.popleft() if (x, y) == end: # If we reach the destination, return dist # Return current distance as shortest path length. for dx, dy in directions: # Explore all four neighbors of this cell. nx, ny = x + dx, y + dy if 0<=nx<rows and 0<=ny<cols and not visited[nx][ny] and grid[nx][ny]==0: visited[nx][ny]=True # Mark neighbor node as visited. queue.append((nx, ny, dist+1)) # Add it to our exploration list along with updated cost/distance value. return -1 # No valid route found between 'start' & 'end'. # Example usage: grid = [ [0, 1, 0], [0, 0, 1], [0, 0, 0] ] print(bfs((0, 0), (2, 2), grid)) ``` 此函数接受三个参数——`start`(源坐标), `end`(目的坐标) 和 `grid`(表示地图布局的一个二维列表) 。 它首先定义了一个方向向量(directions),该变量包含了四个基本移动操作(上、下、左、右); 接着创建了一个布尔型矩阵visited[][],用以跟踪哪些位置已经被探查过; 最后初始化好数据结构之后进入主要逻辑流程即while loop内部执行标准bfs过程直至满足条件退出或穷尽全部可能性仍无果则报错[-1]. #### 结论 上述例子展示了怎样运用 python 编程语言配合 bfs 技巧快速定位两点间最优通路方案之一。值得注意的是实际比赛当中可能会遇到更加复杂的情形比如障碍物形状不规则等等因此建议多加练习熟悉各种变形模式下的应对策略[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值