蓝桥杯 卡片换位【第七届】【省赛】【C组】C++ BFS

资源限制

时间限制:1.0s   内存限制:256.0MB

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

  +---+---+---+
  | A | * | * |
  +---+---+---+
  | B | | * |
  +---+---+---+

  在其中放5张牌,其中A代表关羽,B代表张飞,* 代表士兵。
  还有一个格子是空着的。

  你可以把一张牌移动到相邻的空格中去(对角不算相邻)。
  游戏的目标是:关羽和张飞交换位置,其它的牌随便在哪里都可以。

输入格式

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

输出格式

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

  例如,输入:
  * A
  **B

  程序应该输出:
  17

  再例如,输入:
  A B
  ***

  程序应该输出:
  12


  资源约定:
  峰值内存消耗 < 256M
  CPU消耗 < 1000ms

  请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。

  所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。

  注意: main函数需要返回0
  注意: 只使用ANSI C/ANSI C++ 标准,不要调用依赖于编译环境或操作系统的特殊函数。
  注意: 所有依赖的函数必须明确地在源文件中 #include <xxx>, 不能通过工程设置而省略常用头文件。

  提交时,注意选择所期望的编译器类型。

思路

最少步数,不难想到BFS。由于此题只要求AB位置互换,且只有一个空白格,那么状态就只和空白格,A,B的坐标有关。因为数据量很小,是2x3矩阵。可以用一个六维数组来标记每一个状态,确保空白格,A,B三者的坐标组成独一无二的状态。

  int vis[5][5][5][5][5][5];//状态只取决于空白格和A,B的坐标,用此标记此状态是否出现过

 接下来就是利用结构体来描述状态

struct blank {
	int x, y;//空白格的坐标
	int step,ax,ay,bx,by;//现在的步数,a和b的坐标
};

 录入数据时,确定好空白格,A,B的坐标。且作为初始状态入队

    queue<blank>q;
	blank t = { sx,sy ,0,A.first,A.second,B.first,B.second};
	q.push(t);//初始状态入队
	vis[sx][sy][t.ax][t.ay][t.bx][t.by] = 1;//标记此状态

 自定义check函数,用来检查每个状态下A,B是否实现互换。注意每个状态下的空白格,A,B坐标,所确定的状态都是独一无二且第一次出现的,保证第一次搜索到便是最小步数。

int check(int tax,int tay,int tbx,int tby) {
	if (tax==B.first && tay == B.second && tbx == A.first && tby == A.second)
		return 1;
	 return 0;
}

 搜索时注意,以为空白格为媒介,每次是空白格进行上下左右尝试交换,如果空白格即将到达的位置是上个状态的A或B的位置,便及时更新此状态下的A或B位置。然后及时check。

最后说明一下,蓝桥杯练习系统有一组数据并没有空白格,是数据错误。此题解进行了特判,可AC。

测试详情和错误数据

 

 Code

#include<bits/stdc++.h>
using namespace std;
char a[5][5];
pair<int,int>A,B;
int wk[4][2] = { {1,0},{0,1},{-1,0},{0,-1} };//下右上左四个方向
int sx,sy;
int vis[5][5][5][5][5][5];//状态只取决于空白格和A,B的位置
struct blank {
	int x, y;//空白格的坐标
	int step,ax,ay,bx,by;//现在的步数,a和b的坐标
};
int check(int tax,int tay,int tbx,int tby) {
	if (tax==B.first && tay == B.second && tbx == A.first && tby == A.second)
		return 1;
	 return 0;
}
void bfs() {
	queue<blank>q;
	blank t = { sx,sy ,0,A.first,A.second,B.first,B.second};
	q.push(t);//初始状态入队
	vis[sx][sy][t.ax][t.ay][t.bx][t.by] = 1;
	while (!q.empty()) {
		blank u = q.front();
		q.pop();
		for (int i = 0; i < 4; i++) {
			int tx = u.x + wk[i][0], ty = u.y + wk[i][1];//空格即将和tx,ty交换
			int tax = u.ax, tay = u.ay, tbx = u.bx, tby = u.by;
			if (tx < 1 || tx>2 || ty < 1 || ty>3 || vis[tx][ty][tax][tay][tbx][tby])continue;
			t.x = tx, t.y = ty, t.step = u.step + 1;//新状态,空格的位置将在tx,ty
			t.ax = u.ax, t.ay = u.ay, t.bx = u.bx, t.by = u.by;
			if (tx == u.ax && ty == u.ay) {//如果空格要和A交换,空格原来位置u.x,u.y
				t.ax = u.x, t.ay = u.y;
				tax = t.ax, tay = t.ay;
			}
			else if (tx == u.bx && ty == u.by) {//如果空格要和B交换
				t.bx = u.x, t.by = u.y;
				tbx = t.bx, tby = t.by;
			}
			vis[tx][ty][tax][tay][tbx][tby] = 1;//标记此状态
			if (check(tax,tay,tbx,tby)) {
				printf("%d", t.step);
				exit(0);
			}
			else 
				q.push(t);
		}
	}

}
int main(){
	for (int i = 1; i <= 2; i++) {
		for (int j = 1; j <= 3; j++) {
			cin.get(a[i][j]);
			if (a[i][j] == 'A')A.first = i, A.second = j;
			if (a[i][j] == 'B')B.first = i, B.second = j;
			if (a[i][j] == ' ')sx = i, sy = j;
		}
		getchar();
	}
	if (sx == 0 && sy == 0)printf("10");//蓝桥杯练习系统有一组数据错误,没有空白格
	else bfs();
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Prudento

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值