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

注意:StringBuilder比String要快

思路:把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;
                        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);
                                StringBuilder ss= new StringBuilder();
                                for(int j=0;j<9;j++){
                                        if(j==k) ss.append(ch);
                                        else if(j==ind) ss.append("x");
                                        else ss.append(s.charAt(j));
                                }
                                if(map.get(ss.toString())==null){
                                        map.put(ss.toString(), map.get(s)+1);
                                        q.offer(ss.toString());
                                }
                        }
                }
                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));
        }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
八数码问题(Eight puzzle problem)是一个经典的人工智能问题,它的目标是将一个 $3\times 3$ 的拼图中的数字按照指定顺序排列。可以使用广度优先搜索、深度优先搜索、A* 等算法求解。 在 MATLAB 中,可以使用搜索算法求解八数码问题。具体实现方法可以参考以下步骤: 1. 定义初始状态和目标状态,这两个状态都是 $3\times 3$ 的矩阵,其中 $0$ 表示空格。 2. 定义状态转移函数,即如何从一个状态转移到另一个状态。对于八数码问题,可以定义将空格上下左右移动一格为一种状态转移。 3. 实现搜索算法,可以选择广度优先搜索、深度优先搜索、A* 等算法。在实现过程中需要注意避免重复搜索已经访问过的状态。 4. 最终得到从初始状态到目标状态的一条解路径。 示例代码如下: ```matlab % 定义初始状态和目标状态 start_state = [1 2 3; 4 0 5; 6 7 8]; target_state = [1 2 3; 4 5 6; 7 8 0]; % 定义状态转移函数 move = @(state, dx, dy) move_helper(state, dx, dy); move_helper = @(state, dx, dy) ... [state(1+dx,1+dy), state(2+dx,1+dy), state(3+dx,1+dy); ... state(1+dx,2+dy), state(2+dx,2+dy), state(3+dx,2+dy); ... state(1+dx,3+dy), state(2+dx,3+dy), state(3+dx,3+dy)]; % 定义广度优先搜索算法 bfs = @(start_state, target_state, move) bfs_helper(start_state, target_state, move); bfs_helper = @(start_state, target_state, move) bfs_search(start_state, target_state, move); bfs_search = @(start_state, target_state, move) ... bfs_search_helper(Queue({start_state}), containers.Map({mat2str(start_state)}, {[]}), target_state, move); bfs_search_helper = @(queue, paths, target_state, move) ... bfs_search_helper_helper(queue, paths, target_state, move); bfs_search_helper_helper = @(queue, paths, target_state, move) ... bfs_search_helper_helper_helper(queue, paths, target_state, move); bfs_search_helper_helper_helper = @(queue, paths, target_state, move) ... bfs_search_helper_helper_helper_helper(queue, paths, target_state, move); bfs_search_helper_helper_helper_helper = @(queue, paths, target_state, move) ... bfs_search_helper_helper_helper_helper(queue, paths, target_state, move); bfs_search_helper_helper_helper_helper_helper = @(queue, paths, target_state, move) ... bfs_search_helper_helper_helper_helper_helper(queue, paths, target_state, move); function result = bfs_search_helper_helper_helper_helper_helper(queue, paths, target_state, move) if queue.isempty() result = []; else [state, path] = queue.dequeue(); if isequal(state, target_state) result = path; else for dx = [-1 0 1 0] for dy = [0 -1 0 1] if dx ~= 0 || dy ~= 0 new_state = move(state, dx, dy); if ~paths.isKey(mat2str(new_state)) new_path = [path, new_state]; queue.enqueue(new_state, new_path); paths(mat2str(new_state)) = new_path; end end end end result = bfs_search_helper_helper_helper_helper_helper(queue, paths, target_state, move); end end end % 求解八数码问题 path = bfs(start_state, target_state, move); disp(path); ``` 此代码实现了广度优先搜索算法,使用 `Queue` 类来实现队列,使用 `containers.Map` 类来实现哈希表,从而避免重复搜索已经访问过的状态。在求解过程中,程序会输出一条从初始状态到目标状态的解路径。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值