44行代码AC_卡片换位(DFS变形题 视频讲解 )

励志用尽量少的代码做高效表达


问题描述

你玩过华容道的游戏吗?
这是个类似的,但更简单的游戏。
看下面 3 x 2 的格子
在其中放5张牌,其中A代表关羽,B代表张飞,* 代表士兵。
还有一个格子是空着的。
你可以把一张牌移动到相邻的空格中去(对角不算相邻)。
游戏的目标是:关羽和张飞交换位置,其它的牌随便在哪里都可以。

输入格式:

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

输出格式:

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


建议:这是一道BFS或DFS的变形题,对初学者来说还是有一点压力的。如果你对搜索模板题还没有掌握的话,那么请先比较熟练的掌握深搜、广搜模板后再来尝试解决。


思路分析

思路一:DFS
一开始以为需要“数字华容道”游戏的策略,或者需要一些技巧和推动, 也因此迟迟不敢动笔, 网搜后发现,直接用DFS暴力推过去就可以:

以空格为起点, 上下左右探索, 每次回溯交换位置即可。(-_-|| 我还是不够暴力)

有一点需要注意:
一般来讲,我们做DFS的题时,都是习惯先判断该步是否满足条件,如果满足,则对应的标记数组置1, 回溯,回溯结束后标记数组置0.

但对于本题来说,则需要用if循环判断是否满足条件,共有三种回溯的可能,这样如果每种可能都重复以上的三步, 那么代码就会冗余、易错。

解决办法是:对于每种可能的回溯情况, 无论是否符合,都进行回溯,在下一次回溯开始前统一判断是否符合条件, 如果符合,则vis再置1。这样不仅大大精简了代码,也提高了代码的可读性和效率


思路二:BFS
明天更新, 请持续关注~


一些小技巧:
1. 要使用getchar()处理输入的字符,因为存在空格,scanf或cin无法识别,并且这样的数也很难被存进数组里, 本解法没有使用数组, 以几个数的相对位置来模拟出数组, 请读者细心体会。
2、涉及到坐标的运算时,用结构体模拟坐标求解,往往更为简洁。
3、dfs函数中有一行代码为:if(step > Min) return;在求最短路时加此代码,可以很好的提高代码效率


DFS解法代码展示

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
int Min = inf;
struct{
    
    
	int x, y;
}a, b, k; 

int vis[3][3][3][3][3][3];				//标记数组,标记某点是否走过 

int Next[4][2] = {
    
    {
    
    1,0}, {
    
    -1, 0}, {
    
    0, 1}, {
    
    0, -1}};		//分别代表向右,向左,向上,向下走 

void dfs(int x1, int y1, int x2, int y2, int x, int y, int step) {
    
    
	if(step > Min) return;			//提高效率,步数超过直接return; 
	if(x1==b.x && y1==b.y && x2==a.x && y2==a.y) {
    
    
		Min = min(step, Min);
		return;
	}
	//先判断越界
	if(x<0 || x>1 || y<0 || y>2) return;
	if(vis[x1][y1][x2][y2][x][y] == 1) return;
	
	vis[x1][y1][x2][y2][x][y] = 1; 
	for(int i = 0; i < 4; i++) {
    
    
		int tx = x+Next[i][0];
		int ty = y+Next[i][1];
		if(tx==x1 && ty==y1) 
			dfs(x, y, x2, y2, x1, y1, step+1);
		
		else if(tx==x2 && ty==y2) 
			dfs(x1, y1, x, y, x2, y2, step+1);
		
		else 
			dfs(x1, y1, x2, y2, tx, ty, step+1);
	}
	vis[x1][y1][x2][y2][x][y] = 0;
}

int main() {
    
    
	memset(vis, 0, sizeof(vis)); 
	//输入 
	for(int i = 0; i < 2 ; i++) {
    
    
		for(int j = 0; j < 3; j++) {
    
    
			char s = getchar();
			if(s=='A') {
    
     a.x=i; a.y=j; }
			if(s=='B') {
    
     b.x=i; b.y=j; }
			if(s==' ') {
    
     k.x=i; k.y=j; }
		}
		getchar();
	}

	//处理
	dfs(a.x, a.y, b.x, b.y, k.x, k.y,0); 
	
	cout << Min << endl;
	return 0;
}

这世界就是,一些人总在昼夜不停的努力,而另外一些人,起床就发现世界已经变了。 加油,陌生人!

猜你喜欢

转载自blog.csdn.net/weixin_43899069/article/details/108815821
今日推荐