问题描述
X星球的流行宠物是青蛙,一般有两种颜色:白色和黑色。
X星球的居民喜欢把它们放在一排茶杯里,这样可以观察它们跳来跳去。
如下图,有一排杯子,左边的一个是空着的,右边的杯子,每个里边有一只青蛙。
*WWWBBB
其中,W字母表示白色青蛙,B表示黑色青蛙,*表示空杯子。
X星的青蛙很有些癖好,它们只做3个动作之一:
1. 跳到相邻的空杯子里。
2. 隔着1只其它的青蛙(随便什么颜色)跳到空杯子里。
3. 隔着2只其它的青蛙(随便什么颜色)跳到空杯子里。
对于上图的局面,只要1步,就可跳成下图局面:
WWW*BBB
本题的任务就是已知初始局面,询问至少需要几步,才能跳成另一个目标局面。
输入为2行,2个串,表示初始局面和目标局面。
输出要求为一个整数,表示至少需要多少步的青蛙跳。
X星球的居民喜欢把它们放在一排茶杯里,这样可以观察它们跳来跳去。
如下图,有一排杯子,左边的一个是空着的,右边的杯子,每个里边有一只青蛙。
*WWWBBB
其中,W字母表示白色青蛙,B表示黑色青蛙,*表示空杯子。
X星的青蛙很有些癖好,它们只做3个动作之一:
1. 跳到相邻的空杯子里。
2. 隔着1只其它的青蛙(随便什么颜色)跳到空杯子里。
3. 隔着2只其它的青蛙(随便什么颜色)跳到空杯子里。
对于上图的局面,只要1步,就可跳成下图局面:
WWW*BBB
本题的任务就是已知初始局面,询问至少需要几步,才能跳成另一个目标局面。
输入为2行,2个串,表示初始局面和目标局面。
输出要求为一个整数,表示至少需要多少步的青蛙跳。
样例输入
*WWBB
WWBB*
WWBB*
样例输出
2
样例输入
WWW*BBB
BBB*WWW
BBB*WWW
样例输出
10
数据规模和约定
我们约定,输入的串的长度不超过15
资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗 < 1000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
不要使用package语句。不要使用jdk1.7及以上版本的特性。
主类的名字必须是:Main,否则按无效代码处理。
资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗 < 1000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
不要使用package语句。不要使用jdk1.7及以上版本的特性。
主类的名字必须是:Main,否则按无效代码处理。
当时比赛做这题时,青蛙跳杯子的方式,可以直接看作非星号字符和星号字符的交换,一共6种交换方式,问至少需要几步,可以想到用搜索的方式,且一定为一棵搜索树,明显就是广搜嘛,再看下数据量也很小,重点在于防止青蛙来回跳,局面不变的情况,所以只要做个简单的剪枝肯定能过。
ok下面给上比赛时写的代码
import java.util.*;
class Main {
static String a;//初始局面
static String b;//目标局面
static int cin;//保存星号的位置
static String temp;//保存临时局面
static int count;//树的深度表示搜索的次数
static int num_1=1;//当前这一代节点的个数
static int num_2=0;//保存下一代子节点的个数
public static void main(String[] args) {
Scanner sc=new Scanner (System.in);
a=sc.next();
b=sc.next();
bfs();
System.out.println(count+1);
}
static int findstar(String a) {//确定星号的位置,也就是空杯子的位置
for(int i=0;i<a.length();i++) {
if(a.charAt(i)=='*')
return i;
}
return -1;
}
static String exchange(String a,int m,int n) {//交换两个字符的位置,也就是青蛙跳杯子
char t [] =a.toCharArray();
String tt="";
char temp=t[m];
t[m]=t[n];
t[n]=temp;
for(int i=0;i<t.length;i++) {
tt=tt+t[i];
}
return tt;
}
static void bfs() {
Queue<String> queue=new LinkedList<String>();//队列保存每一代子节点,也就是每次青蛙跳了一次后的局面
TreeSet<String> ts=new TreeSet<>();//剪枝,防止青蛙来回跳相同的局面
while(true) {
if(queue.isEmpty()) {
queue.add(a);
ts.add(a);
}
if(num_1==0) {//每一代的节点为0时,num1重新赋值为num2,num2重置
num_1=num_2;
num_2=0;
count++;
}
String re=queue.poll();
cin=findstar(re);
if(cin-1>=0) {
temp=exchange(re, cin, cin-1);
if(temp.equals(b)) {//找到了直接退出即可
break;
}
if(!ts.contains(temp)) {
queue.add(temp);
ts.add(temp);
num_2++;
}
}if(cin-2>=0) {
temp=exchange(re, cin, cin-2);
if(temp.equals(b)) {
break;
}
if(!ts.contains(temp)) {
queue.add(temp);
ts.add(temp);
num_2++;
}
}
if(cin-3>=0) {
temp=exchange(re, cin, cin-3);
if(temp.equals(b)) {
break;
}
if(!ts.contains(temp)) {
queue.add(temp);
ts.add(temp);
num_2++;
}
}
if(cin+1<a.length()) {
temp=exchange(re, cin, cin+1);
if(temp.equals(b)) {
break;
}
if(!ts.contains(temp)) {
queue.add(temp);
ts.add(temp);
num_2++;
}
}
if(cin+2<a.length()) {
temp=exchange(re, cin, cin+2);
if(temp.equals(b)) {
break;
}
if(!ts.contains(temp)) {
queue.add(temp);
ts.add(temp);
num_2++;
}
}
if(cin+3<a.length()) {
temp=exchange(re, cin, cin+3);
if(temp.equals(b)) {
break;
}
if(!ts.contains(temp)) {
queue.add(temp);
ts.add(temp);
num_2++;
}
}
num_1--;
}
}
}