/*
网格中移动字母
2x3=6个方格中放入ABCDE五个字母,右下角的那个格空着。如图【1.jpg】所示。
和空格子相邻的格子中的字母可以移动到空格中,比如,图中的C和E就可以移动,移动后的局面分别是:
A B
D E C
A B C
D E
为了表示方便,我们把6个格子中字母配置用一个串表示出来,比如上边的两种局面分别表示为:
AB*DEC
ABCD*E
题目的要求是:请编写程序,由用户输入若干表示局面的串,程序通过计算,
输出是否能通过对初始状态经过若干次移动到达该状态。可以实现输出1,否则输出0。初始状态为:ABCDE*
用户输入的格式是:先是一个整数n,表示接下来有n行状态。程序输出也应该是n行1或0
例如,用户输入:
3
ABCDE*
AB*DEC
CAED*B
则程序应该输出:
1
1
0
注意:
请仔细调试!您的程序只有能运行出正确结果的时候才有机会得分!
在评卷时使用的输入数据与试卷中给出的实例数据可能是不同的。
*/
import java.util.Scanner;
import java.util.ArrayList;
import java.util.Queue;
import java.util.LinkedList;
public class 网格中移动字母 {
// 交换元素
public static String swap(String s,int k,int j){
char[] c = s.toCharArray();
char t = c[k];
c[k] = c[j];
c[j] = t;
return new String(c);
}
public static int f(String s){
ArrayList<String> lis = new ArrayList<String>(); // 记录全部交换结果(检查重复用)
Queue<String> queue = new LinkedList<String>(); // 队列(用来测试所有可能)
int[] d = {-1,-3,1,3}; // 定义方向(左,上,右,下)
queue.offer(s); // 入队
lis.add(s); // 加入记录
while(queue.size()>0){
String firstStr = queue.poll(); // 出队
if(firstStr.equals("ABCDE*")) return 1; // 找到结果,退出
int k = firstStr.indexOf("*"); // 找到 "*"号的位置
for(int i=0;i<4;i++){ // 左,上,右,下 四个方向都探测
int j = k+d[i];
if(j>=0&&j<=5){ // 当前方向不越界
String t = swap(firstStr,k,j); // 交换元素
if(!lis.contains(t)){ // lis 不包含 t
queue.offer(t); // 入队
lis.add(t); // 添加记录
}
}
}
}
return 0;
}
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.println("输入整数n");
int n = scan.nextInt();
scan.nextLine();
String[] s = new String[n];
for(int i=0;i<n;i++){
s[i] = scan.nextLine(); // 初始数据
}
for(int i=0;i<n;i++){
System.out.println(f(s[i])); // 得到结果
}
}
}
运行结果:输入整数n
3
ABCDE*
AB*DEC
CAED*B
1
1
0
下边程序输出移动过程:
import java.util.ArrayList;
import java.util.Scanner;
class moveStr {
String str;
String bz;
moveStr(String str, String bz) {
this.str = str;
this.bz = bz;
}
public String getStr() {
return str;
}
public void setStr(String str) {
this.str = str;
}
public String getBz() {
return bz;
}
public void setBz(String bz) {
this.bz = bz;
}
}
public class CopyOfGrid {
String destStr = "ABCDE*";// 目标字符串
ArrayList<String> lis = new ArrayList<String>(); // 记录结果
static boolean result = false;
// 移动字母
public String sawp(String str, int j) {
if (j < 0 || j >= str.length())
return "";
int i = str.indexOf("*");
// 交换位置
char[] c = str.toCharArray();
char temp = c[i];
c[i] = c[j];
c[j] = temp;
return new String(c);
}
// 检查并修改记录
public void check(ArrayList<moveStr> list, String temp, moveStr tempMs) {
if (!temp.equals("") && !lis.contains(temp)) {
String tempBz = tempMs.bz + "->\n" + temp;
moveStr ms1 = new moveStr(temp, tempBz);
list.add(ms1);
lis.add(temp);
}
}
// 寻找解
public void find(String str, String bz) {
ArrayList<moveStr> msLis = new ArrayList<moveStr>();
moveStr ms = new moveStr(str, bz);
msLis.add(ms);// 对象入队
lis.add(str); // 把字符串加入lis
while (msLis.size() > 0) {
moveStr tempMs = msLis.remove(0); // 出队
if (tempMs.str.equals(destStr)) {
result = true;
System.out.println(str + ": 有解 \n" + tempMs.bz);
return;
}
int k = tempMs.str.indexOf("*"); // 找到*号出现的位置
// 向(右)移动
check(msLis, sawp(tempMs.str, k + 1), tempMs);
// 向(上)移动
check(msLis, sawp(tempMs.str, k - 3), tempMs);
// 向(左)移动
check(msLis, sawp(tempMs.str, k - 1), tempMs);
// 向(下)移动
check(msLis, sawp(tempMs.str, k + 3), tempMs);
}
}
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.print("请输入目标状态字符串:");
String user = scan.nextLine();
new CopyOfGrid().find(user, user);
if (!result)
System.out.println("无解");
}
}
运行结果:请输入目标状态字符串:AB*DEC
AB*DEC: 有解
AB*DEC->
ABCDE*