Eleven puzzle

Time Limit: 20000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 463    Accepted Submission(s): 111

Problem Description
Partychen invents a new game named “Eleven Puzzle” .Just like the classic game “Eight Puzzle”,but there some difference between them:The shape of the board is different and there are two empty tiles.

The tile in black means it’s empty

Each step you can move only one tile.

Here comes the problem.How many steps at least it required to done the game.

 
Input
The first line of input contains one integer specifying the number of test cases to follow.

Every case contains five lines to describe the initial status of the board. 0 means empty.

It’s confirmed that the board is legal.

 
Output
Output one line for each testcase.Contain an integer denotes the minimum step(s) it need to complete the game.Or “No solution!” if it’s impossible to complete the game within 20 steps.
 
Sample Input
3
2
1 0 3
4 5 6 7 8
9 0 11
10
0
1 2 3
4 5 6 7 8
9 10 11
0
0
11 10 9
8 7 6 5 4
3 2 1
0
 
Sample Output
2
0
No solution!
 
//8953704	2013-08-15 15:45:09	Accepted	3095	2562MS	27052K	6524 B	Java	zhangyi
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Scanner; public class Hdu3095 {
private static Map<String,Integer> smap = new HashMap<String,Integer>(); //存储从初始状态搜索所到达的状态
private static Map<String, Integer> emap = new HashMap<String, Integer>();//存储从目的状态搜索所到达的状态
private static Status sStatus = null; //初始状态
private static Status eStatus = null;//目的状态
private static int [][] dirs = new int[][]{{1,0},{-1,0},{0,-1},{0,1}}; //方向
private static Queue<Status> sq = new ArrayDeque<Status>();
private static Queue<Status> eq = new ArrayDeque<Status>();
private final static Integer maxLevel = 10;
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int cases = in.nextInt();
while(cases-->0){
inputData(in);
if(eStatus.getStatus().equals(sStatus.getStatus())){//如果初始状态等于目的状态,输出0
System.out.println(0);
}else{
emap.put(eStatus.getStatus(), 0);
smap.put(sStatus.getStatus(), 0);
int step = doublcBFS(sq,eq);
if(step == -1 || step > 20){
System.out.println("No solution!");
}else{
System.out.println(step);
}
}
}
}
/**
* 输入数据
* @param in
*/
private static void inputData(Scanner in){
initResourse();
int value = 0;
sStatus.map[1][3] = in.nextInt();
eStatus.map[1][3] = value++;
for(int i = 2; i <= 4; ++i){
sStatus.map[2][i] = in.nextInt();
eStatus.map[2][i] = value++;
}
for(int i = 1; i <= 5; ++i){
sStatus.map[3][i] = in.nextInt();
eStatus.map[3][i] = value++;
}
for(int i = 2; i <= 4; ++i){
sStatus.map[4][i] = in.nextInt();
eStatus.map[4][i] = value++;
}
sStatus.map[5][3] = in.nextInt();
eStatus.map[5][3] = 0;
smap.clear();
emap.clear();
sStatus.initPoint();
eStatus.initPoint();
sq.clear();
eq.clear();
sq.add(sStatus);
eq.add(eStatus);
} /**
* 初始化数据
*/
private static void initResourse(){
sStatus = new Status();
eStatus = new Status();
for(int i = 0;i < sStatus.map.length; ++i){
Arrays.fill(sStatus.map[i], -1);
Arrays.fill(eStatus.map[i], -1);
}
} /**
* 双向搜索函数
* @param sq 初始状态搜索所需要的队列
* @param eq 目的状态搜索所需要的队列
* @return 初始状态到达目的状态所需要的最小步数,如果在maxLevel数值之内没有结果,则返回-1
*/
private static int doublcBFS(Queue<Status> sq, Queue<Status> eq){
int x, y;
while(!sq.isEmpty()||!eq.isEmpty()){
if(!sq.isEmpty()){ //初始状态搜索
Status s = sq.poll();
for(int i = 0; i < s.points.size(); ++i ){
Point p = s.points.get(i);
for(int j = 0; j < dirs.length; ++j){
x = p.x + dirs[j][0];
y = p.y + dirs[j][1];
if(s.map[x][y] == -1 || s.map[x][y] == 0){
continue;
}
int [][] ms = copyArray(s.map); ms[p.x][p.y] = ms[x][y];
ms[x][y] = 0; Status status = new Status();
status.map = ms;
status.points.add(new Point(x,y));
status.points.add(s.points.get((i+1)%2).copyPoint());
status.level = s.level + 1;
String ss = status.getStatus();
if(emap.containsKey(ss)){ //如果与目的状态搜索到的状态相遇,刚返回步数
return emap.get(ss) + status.level;
}
if(!smap.containsKey(ss) && s.level <= maxLevel){
smap.put(ss, status.level);
sq.add(status);
}
}
}
}
if(!eq.isEmpty()){ //目的状态搜索
Status s = eq.poll();
for(int i = 0; i < s.points.size(); ++i ){
Point p = s.points.get(i);
for(int j = 0; j < dirs.length; ++j){
x = p.x + dirs[j][0];
y = p.y + dirs[j][1];
if(s.map[x][y] == -1 || s.map[x][y] == 0){
continue;
}
int [][] ms = copyArray(s.map);
ms[p.x][p.y] = ms[x][y];
ms[x][y] = 0; Status status = new Status();
status.map = ms;
status.points.add(new Point(x,y));
status.points.add(s.points.get((i+1)%2).copyPoint());
status.level = s.level + 1;
String ss = status.getStatus();
if(smap.containsKey(ss)){//如果与初始状态搜索到的状态相遇,刚返回步数
return smap.get(ss) + status.level;
}
if(!emap.containsKey(ss) && s.level <= maxLevel){
emap.put(ss, status.level);
eq.add(status);
}
}
}
}
}
return -1;
} /**
* 打印一个二维数组
* @param map
*/
private static void show(int [][] map){
StringBuilder sb = new StringBuilder();
for(int i = 1; i < map.length - 1; ++i){
for(int j = 1; j < map[i].length - 1; ++j){
if(map[i][j] == -1){
sb.append(' ');
}else{
sb.append(map[i][j]);
}
}
sb.append('\n');
}
System.out.println(sb.toString());
} /**
* 拷贝一个二维数组
* @param map
* @return
*/
private static int[][] copyArray(int [][] map){
int [][] m = new int[map.length][map[0].length];
for(int i = 0; i < map.length; ++i){
System.arraycopy(map[i],0,m[i],0,map[i].length);
}
return m;
}
} /**
* 存储状态
* @author Administrator
*
*/
class Status{
final static int N = 7;
int [][] map; //当前地图
List<Point> points; //当前0点坐标
int level = 0; //到达当前状态所需步数
public Status(){
map = new int[N][N];
points = new ArrayList<Point>();
level = 0;
}
public Status(int [][] map, List<Point> points, int level){
this.map = map;
this.points = points;
this.level = level;
}
public void initPoint(){
for(int i = 1; i < map.length -1; ++i){
for(int j = 1; j < map[i].length - 1; ++j){
if(map[i][j] == 0){
points.add(new Point(i,j));
}
}
}
} /**
* 返回一个可唯一标识当前状态的字符串
* @return
*/
public String getStatus(){
StringBuilder sb = new StringBuilder();
for(int i = 1; i < map.length -1; ++i){
for(int j = 1; j < map[i].length -1; ++j){
if(map[i][j] != -1){
sb.append(map[i][j]);
sb.append(',');
}
}
}
return sb.toString();
}
}
/**
* 坐标
* @author Administrator
*
*/
class Point{
int x;
int y;
public Point(){ }
public Point(int x, int y){
this.x = x;
this.y = y;
}
/**
* 拷贝一个坐标
* @return
*/
public Point copyPoint(){
Point p = new Point();
p.x = x;
p.y = y;
return p;
}
}

双向广搜



Eleven puzzle_hdu_3095(双向广搜).java的更多相关文章

  1. HDU--杭电--1195--Open the Lock--深搜--都用双向广搜,弱爆了,看题了没?语文没过关吧?暴力深搜难道我会害羞?

    这个题我看了,都是推荐的神马双向广搜,难道这个深搜你们都木有发现?还是特意留个机会给我装逼? Open the Lock Time Limit: 2000/1000 MS (Java/Others)  ...

  2. 双向广搜 POJ 3126 Prime Path

      POJ 3126  Prime Path Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 16204   Accepted ...

  3. 双向广搜 codevs 3060 抓住那头奶牛

    codevs 3060 抓住那头奶牛 USACO  时间限制: 1 s  空间限制: 16000 KB  题目等级 : 黄金 Gold   题目描述 Description 农夫约翰被告知一头逃跑奶牛 ...

  4. 双向广搜+hash+康托展开 codevs 1225 八数码难题

    codevs 1225 八数码难题  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond   题目描述 Description Yours和zero在研究A*启 ...

  5. 【双向广搜+逆序数优化】【HDU1043】【八数码】

    HDU上的八数码 数据强的一B 首先:双向广搜 先处理正向搜索,再处理反向搜索,直至中途相遇 visit 和 队列都是独立的. 可以用一个过程来完成这2个操作,减少代码量.(一般还要个深度数组) 优化 ...

  6. nyoj 523 双向广搜

    题目链接: http://acm.nyist.net/JudgeOnline/problem.php?pid=523 #include<iostream> #include<cstd ...

  7. poj 3131 Cubic Eight-Puzzle 双向广搜 Hash判重

    挺不错的题目,很锻炼代码能力和调试能力~ 题意:初始格子状态固定,给你移动后格子的状态,问最少需要多少步能到达,如果步数大于30,输出-1. 由于单向搜索状态太多,搜到二十几就会爆了,所以应该想到双向 ...

  8. 万圣节后的早晨&&九数码游戏——双向广搜

    https://www.luogu.org/problemnew/show/P1778 https://www.luogu.org/problemnew/show/P2578 双向广搜. 有固定起点终 ...

  9. Eight_pku_1077(广搜).java

    Eight Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 21718   Accepted: 9611   Special ...

随机推荐

  1. 使用Nginx的配置对cc攻击进行简单防御

    ddos攻击:分布式拒绝服务攻击,就是利用大量肉鸡或伪造IP,发起大量的服务器请求,最后导致服务器瘫痪的攻击. cc攻击:类似于ddos攻击,不过它的特点是主要是发起大量页面请求,所以流量不大,但是却 ...

  2. jdbc 回顾

    JDBC实现基本的CRUD示例 private static void insertTest() throws SQLException { String dbURL = "jdbc:mys ...

  3. 提高sqlmap爆破效率

     提高sqlmap爆破效率 sqlmap在注入成功后,会尝试获取数据库和表的结构.对于MSSQL.MySQL.SQLite之类数据库,sqlmap可以通过系统数据库.系统数据表获取数据库和表的结构.但 ...

  4. 【线段树】Petrozavodsk Summer Training Camp 2016 Day 6: Warsaw U Contest, XVI Open Cup Onsite, Sunday, August 28, 2016 Problem H. Hay

    有一些草,一开始高度都是0,它们的生长速率不同. 给你一些单增的日期,在这些日期要将>b的草的部分都割掉,问你每次割掉的部分有多少. 将草的生长速率从大到小排序,这样每次割掉的是一个后缀,而且不 ...

  5. ubuntu16 安装docker

    本文开发环境为Ubuntu 16.04 LTS 64位系统,通过apt的docker官方源安装最新的Docker CE(Community Edition),即Docker社区版,是开发人员和小型团队 ...

  6. bzoj 1650: [Usaco2006 Dec]River Hopscotch 跳石子

    1650: [Usaco2006 Dec]River Hopscotch 跳石子 Time Limit: 5 Sec  Memory Limit: 64 MB Description Every ye ...

  7. bootstrap学习(全局CSS样式)(一)

    布局容器 bootstrap需要为页面内容和栅格系统包裹一个.container容器.我们提供了两个作词用处的类.注意,由于padding等属性的原因,这两种容器类不能互相嵌套. .container ...

  8. Highcharts做统计图。

    <script> $(function () { var areasplineData = [[1447916401000,3],[1447918201000,4]]; var typeR ...

  9. #Java Web累积#JS动态加载所有同name的select的option

      项目需求: 某一页面,页面使用多列table,每个table中有同相同的<select>,select的option不确定,根据Server端的配置来,所以option需要动态加载: ...

  10. Ubuntu 16.04下使用VMware安装CentOS 6.9然后在里面再安装KVM之后配置网桥无法上网的问题

    别试了,这个问题无法解决,已经使用VMware安装了一层虚拟机,然后在里面再安装KVM,网络层次已经变了,即使配置了网桥同样无法上网. 可是这样试一下,不一定成功:把VMware的虚拟机绑定另一张物理 ...