845. 八数码(bfs+map)

在一个3×3的网格中,1~8这8个数字和一个“X”恰好不重不漏地分布在这3×3的网格中。

例如:

1 2 3
X 4 6
7 5 8

在游戏过程中,可以把“X”与其上、下、左、右四个方向之一的数字交换(如果存在)。

我们的目的是通过交换,使得网格变为如下排列(称为正确排列):

1 2 3
4 5 6
7 8 X

例如,示例中图形就可以通过让“X”先后与右、下、右三个方向的数字交换成功得到正确排列。

交换过程如下:

1 2 3   1 2 3   1 2 3   1 2 3
X 4 6   4 X 6   4 5 6   4 5 6
7 5 8   7 5 8   7 X 8   7 8 X

现在,给你一个初始网格,请你求出得到正确排列至少需要进行多少次交换。

输入格式

输入占一行,将3×3的初始网格描绘出来。

例如,如果初始网格如下所示:
1 2 3

x 4 6

7 5 8

则输入为:1 2 3 x 4 6 7 5 8

输出格式

输出占一行,包含一个整数,表示最少交换次数。

如果不存在解决方案,则输出”-1”。

输入样例:

2  3  4  1  5  x  7  6  8

输出样例

19

思路:把8数码当成一个字符串处理     字符的位置-由一维字符串得到在3x3矩阵中的位置     然后对于四个方向广搜,交换字符的位置得到一个新的字符串   用map记录当前的状态,有的话就不能再走,没有则记录新状态

代码:
import java.util.ArrayDeque;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

public class Main{
        static Map<String,Integer> map=new HashMap<String, Integer>();
        static ArrayDeque<String> q=new ArrayDeque<>();
        static int dx[]={1,-1,0,0};
        static int dy[]={0,0,1,-1};
        static int bfs(String start){
                q.offer(start);
                map.put(start, 0);

                while(!q.isEmpty()){

                        String s=q.poll();
                        int distance=map.get(s);
                        if(s.equals("12345678x"))   return distance;

                        int k=s.indexOf(‘x‘);
                        int x=k/3,y=k%3;//由一维的位置得到在3x3矩阵中的位置
                        for(int i=0;i<4;i++){
                                int xx=x+dx[i];
                                int yy=y+dy[i];
                                if(xx<0 || yy<0 || xx>=3 || yy>=3) continue;

                                int ind=3*xx+yy;
                                char ch=s.charAt(ind);
                                String ss="";
                                for(int j=0;j<9;j++){//交换两个位置的字符得到新字符串
                                        if(j==k) ss+=ch;
                                        else if(j==ind) ss+=‘x‘;
                                        else ss+=s.charAt(j);
                                }
                                if(map.get(ss)==null){
                                        map.put(ss, map.get(s)+1);
                                        q.offer(ss);
                                }
                        }
                }
                return -1;
        }
        public static void main(String[] args) {
                Scanner scan=new Scanner(System.in);
                String start="";
                for(int i=1;i<=9;i++){
                     String ch=scan.next();
                     start+=ch;
                }
                System.out.println(bfs(start));
        }
}

原文地址:https://www.cnblogs.com/qdu-lkc/p/12242437.html

时间: 2024-08-12 19:26:36

845. 八数码(bfs+map)的相关文章

poj 1077 八数码(BFS+康托展开)

1 /* 2 题意:八数码问题,给出3*3的矩阵含1~8以及x,给出一个符合的解使得移动后的矩阵的顺序为1~8,最后为x 3 4 题解:BFS 5 需要用到康托展开来表示状态,不然数组无法完全表示所有状态,这样BFS就无法判断找不到解的情况(status 6 的0ms,0KB究竟是怎么做到的,简直不能想象=.=) 7 */ 8 #include <cstdio> 9 #include <cstring> 10 #include <queue> 11 #include &

HDU1043 八数码(BFS + 打表)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1043 , 康托展开 + BFS + 打表. 经典八数码问题,传说此题不做人生不完整,关于八数码的八境界:http://www.cnblogs.com/goodness/archive/2010/05/04/1727141.html 我自己是用哈希(康托展开) + BFS  + 打表过的,第三重境界. 由于一些高级的搜索现在还没学,所以目前能升级的也就是用双向BFS来做了,等过几天有心情了来做. 本文

八数码(map版)

八数码 map真是个奇技淫巧好东西 可以十分简单的实现hash,当然速度就不敢保证了 因为九位数不算很大,完全可以用int存下,所以便将八数码的图像转换成一个int型的数字 #include<iostream> #include<queue> #include<map> #include<algorithm> using namespace std; int d[4]={-3,-1,1,3}; struct node { int position;//用0表

code1225 八数码Bfs

Bfs搜索 1.把棋盘直接作为状态: #include<iostream> #include<cstring> #include<queue> #include<cstdlib> using namespace std; const int n=9; const int Size=4; int flag; struct Point{ int x,y; }; struct Node{ int board[Size][Size]; Point space; in

AcWing 845. 八数码

https://www.acwing.com/problem/content/847/ #include<bits/stdc++.h> using namespace std; int bfs(string start) { string end="12345678x"; queue<string>q; unordered_map<string,int>d; //距离数组 q.push(start); // 先把start放进去 d[start]=0

luogu_1379 八数码难题

八数码-->BFS+set 1 #include<iostream> 2 #include<cstdlib> 3 #include<cstdio> 4 #include<cstring> 5 #include<set> 6 using namespace std; 7 struct aaa{ 8 int map[4][4]; 9 int dep,x,y; 10 }que[370000]; 11 set<int> ssr; 12

HDU 1043 Eight八数码解题思路(bfs+hash 打表 IDA* 等)

题目链接 https://vjudge.net/problem/HDU-1043 经典的八数码问题,学过算法的老哥都会拿它练搜索 题意: 给出每行一组的数据,每组数据代表3*3的八数码表,要求程序复原为初始状态 思路: 参加网站比赛时拿到此题目,因为之前写过八数码问题,心中暗喜,于是写出一套暴力bfs+hash,结果TLE呵呵 思路一:bfs+hash(TLE) 1 #include <cstdio> 2 #include <cstring> 3 #include <queu

cdoj 1380 Xiper的奇妙历险(2) [八数码问题 bfs + 预处理]

快要NOIP 2016 了,现在已经停课集训了.计划用10天来复习以前学习过的所有内容.首先就是搜索. 八数码是一道很经典的搜索题,普通的bfs就可求出.为了优化效率,我曾经用过康托展开来优化空间,甚至还用过A*来优化时间.不过这道题懒得写了,就一个普普通通的bfs,再加上一个stl 的map就水过了. 首先题目要求有多达10000组数据,依次搜索肯定是不行的,我试过用A*来写,第2组数据就会T掉,所以我们考虑用一个预处理.从末尾状态搜索所有可行的状态,并用一个map来存储答案.然后就很好写了.

BFS(八数码) POJ 1077 || HDOJ 1043 Eight

题目传送门1 2 题意:从无序到有序移动的方案,即最后成1 2 3 4 5 6 7 8 0 分析:八数码经典问题.POJ是一次,HDOJ是多次.因为康托展开还不会,也写不了什么,HDOJ需要从最后的状态逆向搜索,这样才不会超时.判重康托展开,哈希也可. POJ //#include <bits/stdc++.h> #include<iostream> #include<algorithm> #include<string> #include<stack