c语言试题c组卡片换位,蓝桥杯 卡片换位 - 李韬|aitom|机器人|SLAM - OSCHINA - 中文开源技术交流社区...

题目描述:

卡片换位

你玩过华容道的游戏吗?

这是个类似的,但更简单的游戏。

看下面 3 x 2 的格子

+---+---+---+

|  A  |  *   |  *   |

+---+---+---+

|   B  |      |  *  |

+---+---+---+

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

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

输出格式:

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

例如,输入:

* A

**B

程序应该输出:

17

再例如,输入:

A B

***

程序应该输出:

12

思路:

这道题从字面意思是交换a和b,但是根据规则移动的条件只能移动空格周围的卡片。所以基本等价于移动空格,把各种情况遍历一遍找到一种a和b互换的情况。

由于空格只能移动到相邻位置,所以思路也就明确了可以用广度优先搜索。

空格可以移动有四个方位,上下左右。每移动一次就保存移动后的卡片排序,并且移动到该状态需要的步数是移动前的需要的步数加1.

终将有一次会找到一个卡片序列使得a和b相对起始序列是互换的。

简易代码版:

import java.util.HashMap;

import java.util.LinkedList;

import java.util.Queue;

public class ExchangeAB {

public static void main(String[] args) {

String in = "A B***";

int aOrigin = in.indexOf("A");

int bOrgin = in.indexOf("B");

// 保存到某个局面需要的步数

HashMap save = new HashMap<>();

// 广度优先的队列

Queue queue = new LinkedList<>();

queue.add(in);

save.put(in, 0);

// 移动的方向上下左右

int[][] move = { { -1, 0 }, { 1, 0 }, { 0, -1 }, { 0, 1 } };

// 广度优先固定格式

while (!queue.isEmpty()) {

String nowStr = queue.poll();

int nowStep = save.get(nowStr);

// 如果A和B已经交换直接输出

if (nowStr.indexOf("B") == aOrigin && nowStr.indexOf("A") == bOrgin) {

System.out.println(nowStep);

return;

}

// 定位到空格的位置

int spacePos = nowStr.indexOf(" ");

int x = spacePos / 3;

int y = spacePos % 3;

char[] nowArr = nowStr.toCharArray();

// 向周围扩散

for (int[] arr : move) {

int tempx = x + arr[0];

int tempy = y + arr[1];

if (tempx >= 0 && tempx < 2 && tempy >= 0 && tempy < 3) {

// 移动空格位置

exchange(x, y, tempx, tempy, nowArr);

String tempStr = String.valueOf(nowArr);

if (save.get(tempStr) == null) {// 如果这个局面没来过则添加到队列

queue.add(tempStr);

save.put(tempStr, nowStep + 1);

}

// 复原空格位置方便给下个方向移动

exchange(x, y, tempx, tempy, nowArr);

}

}

}

}

public static void exchange(int x1, int y1, int x2, int y2, char[] arr) {

int pos1 = x1 * 3 + y1;

int pos2 = x2 * 3 + y2;

char temp = arr[pos1];

arr[pos1] = arr[pos2];

arr[pos2] = temp;

}

}

详细代码版:

package real;

import java.awt.Point;

import java.util.HashMap;

import java.util.LinkedList;

import java.util.Queue;

public class CardMove {

//有四个移动方位

public static final int[][] move = { { 1, 0 }, { -1, 0 }, { 0, -1 },

{ 0, 1 } };

public static void main(String[] args) {

String a = "* A**B";//起始顺序(删除换行)

Queue queue = new LinkedList();

HashMap qmap = new HashMap();

//保存初始状态卡片A和B的位置

int posia = a.indexOf('A');

int posib = a.indexOf('B');

Point preblank = new Point();

Point blank = new Point();

//广度优先搜索起点是初始的卡片顺序

queue.add(a);

//保存初始状态顺序,到达该状态需要0步

qmap.put(a, 0);

String temp;

//广度优先搜索固定套路^_^一个循环

while (!queue.isEmpty()) {

//从队列中拿一个卡片序列出来

a = queue.poll();

temp = a;

//判断当前卡片顺序是否满足条件(a,b相对于初始顺序互换了)

if (a.charAt(posib) == 'A' && a.charAt(posia) == 'B') {

System.out.println(qmap.get(a));

break;

}

//找到空格所在位置方便进行移动遍历

int posiblank = a.indexOf(' ');

//计算出空格坐标

preblank.x = posiblank / 3;

preblank.y = posiblank % 3;

//进行移动遍历,空格有四个方向可以走上下左右

for (int[] arr : move) {

blank.x = preblank.x + arr[0];

blank.y = preblank.y + arr[1];

//判断移动后的目标位置是否合法(是不是出了矩阵)

if (blank.x >= 0 && blank.x <= 1 && blank.y >= 0

&& blank.y <= 2) {

//把字符串转字符数组,方便进行互换操作

char[] achar = a.toCharArray();

int tempindex = blank.x * 3 + blank.y;

//将空格移动到目标位置(就是将目标位置和空格交换)

char tempchar = achar[tempindex];

achar[tempindex] = achar[posiblank];

achar[posiblank] = tempchar;

//判断移动后的卡片序列是不是以前就走过了,走过了就不用再走了

if (qmap.get(String.valueOf(achar)) != null)

continue;

//把产生的新的序列保存下来,到的新的序列所需要的步数是老的序列的步数+1

qmap.put(new String(achar), qmap.get(temp) + 1);

//将新的序列加入到队列中,用于后面的搜索

queue.add(new String(achar));

}

}

}

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值