1、问题描述
X星球的流行宠物是青蛙,一般有两种颜色:白色和黑色。
X星球的居民喜欢把它们放在一排茶杯里,这样可以观察它们跳来跳去。
如下图,有一排杯子,左边的一个是空着的,右边的杯子,每个里边有一只青蛙。
*WWWBBB
其中,W字母表示白色青蛙,B表示黑色青蛙,*表示空杯子。
X星的青蛙很有些癖好,它们只做3个动作之一:
1. 跳到相邻的空杯子里。
2. 隔着1只其它的青蛙(随便什么颜色)跳到空杯子里。
3. 隔着2只其它的青蛙(随便什么颜色)跳到空杯子里。
对于上图的局面,只要1步,就可跳成下图局面:
WWW*BBB
本题的任务就是已知初始局面,询问至少需要几步,才能跳成另一个目标局面。
输入为2行,2个串,表示初始局面和目标局面。
输出要求为一个整数,表示至少需要多少步的青蛙跳。
例如:
输入格式
*WWBB
WWBB*
则程序应该输出:
2
再例如,
输入格式
WWW*BBB
BBB*WWW
则程序应该输出:
10
2、代码实现
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
import java.util.Set;
public class Main{
//原字符串
static String source;
//目标字符串
static String target;
//去重,存储每次的状态
static Set<String> set = new HashSet<>();
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
source = scanner.next();
target = scanner.next();
bfs();
}
public static void bfs() {
//创建一个队列
Queue<Node> queue = new LinkedList<>();
//存储原字符串
queue.offer(new Node(source,0));
//获取字符串的长度,下面要用到
int len = source.length();
while(!queue.isEmpty()) {
//取出第一个结点
Node node = queue.poll();
//当前结点的状态跟目标字符串一样的话,就结束了
if(target.equals(node.status)) {
System.out.println(node.step);
return;
}
//将当前结点转为数组,并获取跳的次数
char[] arr = node.status.toCharArray();
int step = node.step;
//开始广搜,思想:第i个非*字符和*字符交换位置
for(int i = 0;i < len;i++) {
//arr[i]是青蛙,不能是*
if(arr[i] != '*') {
// 青蛙跳的6种方式
for(int j = -3;j <= 3;j++) {
//过滤
if(i + j < 0 || i + j >= len || j == 0 || arr[i + j] != '*') {
continue;
}
//将青蛙和*进行交换
swap(arr,i,i + j);
//获取交换后的状态
node = new Node(String.valueOf(arr),step + 1);
//过滤,去重,剪枝,效率会提高
if(!set.contains(node.status)) {
set.add(node.status);
queue.add(node);
}
//回溯
swap(arr,i,i + j);
}
}
}
}
}
//交换
public static void swap(char[] arr,int a,int b) {
char t = arr[a];
arr[a] = arr[b];
arr[b] = t;
}
}
class Node{
//当前字符串的状态
String status;
//跳的次数
Integer step;
public Node(String status, Integer step) {
super();
this.status = status;
this.step = step;
}
}