题目链接:P1032
一个坑点非常多的题啊! 真的恶心
(1) 输入的时候是没有给有多少个变换规则的,只是给了最多6个,这个在java中实现我们可以用sc.hasNext(),在读完的时候我们按 Ctrl+z 即可。
(2)在进行变换的时候,我们要知道一个串里面可能有几个地方都满足这个变换规则,假设 x:abcdabc 变换规则为:abc可以换成x,那这里会出现2中情况,一种是变成xdabc,还一种是abcdx,所以这里我们在进行bfs的时候访问一个规则时我们需要把所有可能性都加入到队列中。
(3)随着串与规则匹配的次数越来越多,这里面可能会出现一个串经过一种规则后变成了另外一个我们已经加入到队列里面的串,我们必须要把这种可能性剪掉,也可以就叫做记忆化搜索,意思就是如果这个串我已经加入到队列里面去了,我就不加了,直接跳过。
代码:
package y2020_2_11;
import java.util.*;
public class P1032 {
static String A;
static String B;
static String x[];
static String y[];
static int nn = 0;
static HashMap<String,Integer> hash = new HashMap<String,Integer>();// 用映射来实现这个串我有没有访问过
static void bfs(String s,int n){
string str = new string(s,n);
Queue<string> q = new LinkedList<string>();
q.add(str);
while(!q.isEmpty()){
string node = q.peek();
if(node.s.equals(B)){ // 已经与目的串相同
System.out.println(node.n);
return;
}
if(hash.containsKey(node.s)){ // 我已经访问过这个串了
q.poll();
continue;
}
if(node.n == 10) // 此时已经10步了,这个点我们就不需要扩展了,扩展的点就直接11不了,就直接超过了
q.poll();
hash.put(node.s,1); // 记忆化,标记该串我访问过
for(int i = 0;i < nn;i++){
int p = 0;
while(node.s.indexOf(x[i],p) != -1){ // indexOf 放回从p位置开始第一次遇到x[i]的位置,如果串中没有的话放回-1
p = node.s.indexOf(x[i],p);// 让p等于这个位置,方便我们整理串
q.add(new string(node.s.substring(0,p)+y[i]+node.s.substring(p+x[i].length()),node.n+1)); // 这个大家可以好好看看 就是把串整合起来
p++; // 从下一个位置继续找,看会不会存在(2)这种可能
}
}
q.poll();
}
System.out.println("NO ANSWER!"); // 如果到这里这个函数还没有return说明无解了
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
A = sc.next();
B = sc.next();
x = new String[6];
y = new String[6];
while(sc.hasNext()){
x[nn] = sc.next();
y[nn++] = sc.next();
}
bfs(A,0);
}
}
class string{
String s;
int n;
string(String s,int n){
this.s = s;
this.n = n;
}
}