你玩过华容道的游戏吗?
这是个类似的,但更简单的游戏。
看下面 3 x 2 的格子
+---+---+---+
| A | * | * |
+---+---+---+
| B | | * |
+---+---+---+
在其中放5张牌,其中A代表关羽,B代表张飞,* 代表士兵。
还有一个格子是空着的。
你可以把一张牌移动到相邻的空格中去(对角不算相邻)。
游戏的目标是:关羽和张飞交换位置,其它的牌随便在哪里都可以。
输入格式
输入两行6个字符表示当前的局面
输出格式
一个整数,表示最少多少步,才能把AB换位(其它牌位置随意)
例如,输入:
* A
**B
程序应该输出:
17
再例如,输入:
A B
***
程序应该输出:
12
本题就是一个典型的bfs的应用
为啥是bfs而不是dfs呢因为,他要步数最小,那么就肯定是bfs啦
bfs大家都会,本题比较有一意思的地方就是状态!!!
如果我们想着移动A或者B那么即使很明确是bfs也觉得很复杂,很难写出来,我当时也是这样,后来发现我们可以去移动空格!!!瞬间变得简单起来!!!确实还是要多动脑子
本题呢就是因为2*3麻数据量还是比较小的,所以我直接把位置改成了string用来记忆,毕竟这样用set去重就简单多了哈哈哈
代码如下
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Set;
public class Main卡片换位 {
static int a,b,k,tp;
static int fx[]= {-1,1,4,-4};//换的方向
public static void main(String[] args) throws IOException {
BufferedReader x = new BufferedReader(new InputStreamReader(System.in));
PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
String s1=x.readLine();
String s2=x.readLine();
String s3=s1+"+"+s2;//用+号区分行
for(int i=0;i<7;i++)//确认位置
if(s3.charAt(i)=='A')
a=i;
else if(s3.charAt(i)=='B')
b=i;
else if(s3.charAt(i)==' ')
k=i;
bfs(s3);
out.println(tp);
out.flush();
}
public static void bfs(String s) {
Set<String> bj=new HashSet<String>();//用来出现过的
Queue<Det> q=new LinkedList<Det>();
Det t=new Det(s, k, 0);
q.add(t);
while(!q.isEmpty()) {
t=q.poll();
if(t.s.charAt(b)=='A'&&t.s.charAt(a)=='B') {//找到就退出
tp=t.tep;
return;
}
for(int i=0;i<4;i++) {
int xx=t.x+fx[i];
if(xx>=0&&xx<3||xx>3&&xx<=6) {//上下左右移动
char cc[]=t.s.toCharArray();//移动,也就是交换
cc[t.x]=cc[xx];
cc[xx]=' ';
String ss=new String(cc);
if(!bj.contains(ss)) {
q.add(new Det(ss, xx, t.tep+1));//入队
bj.add(ss);
}
}
}
}
}
}
class Det{
public int x;//点的位置
public String s;//现在的位置
public int tep;//几步了
public Det(String s,int x,int tep) {
this.s=s;
this.tep=tep;
this.x=x;
}
}