挑战程序设计竞赛(算法和数据结构)——19.2九宫格拼图问题的JAVA实现
Posted 小乖乖的臭坏坏
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了挑战程序设计竞赛(算法和数据结构)——19.2九宫格拼图问题的JAVA实现相关的知识,希望对你有一定的参考价值。
题目&解题思路:
代码:
import java.io.PushbackInputStream;
import java.util.*;
public class Puzzle_9
public static final int N = 3;
public static final int N2 = 9;
public static final int dx[] = -1, 0, 1, 0;
public static final int dy[] = 0, -1, 0, 1;
public static final char dir[] = 'u', 'l', 'd', 'r';
public static class Puzzle implements Comparable
int f[] = new int[N2];
int space;
String path;
@Override
public int compareTo(Object obj)
Puzzle p = (Puzzle)obj;
int cnt = 0;
for (int i=0;i<N2;i++)
if(p.f[i]==this.f[i])cnt++;
else
return -1;
if (cnt==9)
return 0;
else
return -1;
//如果第i个元素对应的不是(i+1),那么就返回false
public static boolean isTarget(Puzzle p)
for (int i=0;i<N2;i++)
if(p.f[i]!=(i+1))
return false;
return true;
public static String bfs(Puzzle s)
ArrayDeque<Puzzle> Q = new ArrayDeque<>();
HashSet<Puzzle> V = new HashSet<>();
Puzzle u = new Puzzle();
Puzzle v = new Puzzle();
s.path = "";//将传入的路径设置为空
Q.addLast(s);//入队
V.add(s);//将s的状态添加进入历史访问集合
while (!Q.isEmpty())
u = copyPuzzle(Q.peek());
Q.removeFirst();
if(isTarget(u))return u.path;//如果完成目标了,则返回u的路径
int sx = u.space/N;//用于对当前空格的定位
int sy = u.space%N;
for (int r=0;r<4;r++)
int tx = sx + dx[r];//设置4个方位的移动
int ty = sy + dy[r];
if(tx<0||ty<0||tx>=N||ty>=N)continue;
v = copyPuzzle(u);
//移动空格
int temp = v.f[u.space];
v.f[u.space] = v.f[tx*N+ty];
v.f[tx*N+ty] = temp;
//设置空格位置
v.space = tx*N+ty;
//判断这个状态历史上是否发生,如果发生就跳过,没发生就执行:
if(!isContain(V,v))
V.add(v);//将当前状态加入历史记录集合
v.path += dir[r];//将移动操作添加到其路径中
Q.addLast(v);//将当前状态入队等待操作
return "unsolvable";
public static boolean isContain(HashSet<Puzzle> V, Puzzle v)
Iterator<Puzzle> it = V.iterator();
while(it.hasNext())
Puzzle element = it.next();
if(element.compareTo(v)==0)
return true;
;
return false;
public static Puzzle copyPuzzle(Puzzle p)
Puzzle p1 = new Puzzle();
p1.space = p.space;
p1.path = p.path;
for (int i=0;i<N2;i++)
p1.f[i] = p.f[i];
return p1;
public static void main(String[] args)
Scanner cin = new Scanner(System.in);
Puzzle in = new Puzzle();
for (int i=0;i<N2;i++)
in.f[i] = cin.nextInt();
if(in.f[i] == 0)
in.f[i] = N2;
in.space = i;
String ans = bfs(in);
System.out.println(ans.length());
输入:
1 3 0
4 2 5
7 8 6
输出:
4
这次的代码有很多值得玩味的地方,虽然耽误了很多时间,踩了很多坑,也总结很多经验。
1.目的:想要用对象2存入对象1中的所有值。
错误做法:将对象2赋值给对象1。
结果:更改对象2时,对象1也会同时更改。
原因:将对象2赋值给对象1的动作实际上是把对象2的地址赋给对象1,因此无论操作对象1还是对象2都是操作的同一片内存空间。
解决方案:为对象1开辟一份新的内存空间,将对象2中所有的值赋给对象1,甚至是对象1中的数组也要以元素为单位一一赋值。
示例代码:
public static Puzzle copyPuzzle(Puzzle p)
Puzzle p1 = new Puzzle();
p1.space = p.space;
p1.path = p.path;
for (int i=0;i<N2;i++)
p1.f[i] = p.f[i];
return p1;
2.目的:如何自定义比较两个对象是否一致。
错误做法:再写一个函数比较,很麻烦。
解决方案:实现Comparable接口,并重写compareTo方法,这样就可以定义一个比较器,从而比较别的对象是不是和自己相同。
示例代码:
public static class Puzzle implements Comparable
int f[] = new int[N2];
int space;
String path;
@Override
public int compareTo(Object obj)
Puzzle p = (Puzzle)obj;
int cnt = 0;
for (int i=0;i<N2;i++)
if(p.f[i]==this.f[i])cnt++;
else
return -1;
if (cnt==9)
return 0;
else
return -1;
3.对于一个ArrayDeque队列,添加删除元素时,最好用addLast,removeFirst这样的函数,否则使用push、add、remove、pop就不确定从哪头插入元素删除元素了,这就失去了队列的意义,也是今天卡了很久的原因
以上是关于挑战程序设计竞赛(算法和数据结构)——19.2九宫格拼图问题的JAVA实现的主要内容,如果未能解决你的问题,请参考以下文章
挑战程序设计竞赛(算法和数据结构)——分割(下)&快速排序的JAVA实现
挑战程序设计竞赛(算法和数据结构)——7.1归并排序JAVA实现
挑战程序设计竞赛(算法和数据结构)——16.13线段相交问题(曼哈顿算法)的JAVA实现
挑战程序设计竞赛(算法和数据结构)——3.6希尔排序的JAVA实现