数据结构和算法 第二小题 九宫重排(1)

   参考了csdn里的一篇文章(leetcode上没找到),他用C++写的, 双向bfs队列搜索。我把C++的代码改成了java,链接:https://blog.csdn.net/qq_45775045/article/details/112548439

     实验任务:
1)对九宫重排问题,建立图的启发式搜索求解方法;
2)用A*算法求解九宫重排问题。

实验要求:
3х3九宫棋盘,放置数码为1~8的8个棋子,棋盘中留有一个空格,空格周围的棋子可以移动到空格中,从而改变棋盘的布局。根据给定初始布局和目标布局,移动棋子从初始布局到达目标布局,求解移动步骤并输出。请设计算法,使用合适的搜索策略,在较少的空间和时间代价下找到最短路径。

工具:IDEA  jdk1.8

总结:没有成功。。。敲了半天跑不动,无语了。

*****************

能跑了,字符交换后没有赋给原字符串,导致永远返回-1.还有个问题,起点和终点相等也会返回-1.

讲解:BFS:所有因为展开节点而得到的子节点都会被加进一个先进先出的队列中。java库的功能写的很多,很方便,但也不够纯粹了,栈

和队列看起来居然很相似。增删就有两种方法。对于这些功能选取合适的即可,其他忽视。

单向BFS太慢了,双向快很多。这里有几个细节,1.起点和终点的visited设置的值不同,这是为了最终前后相遇的判断。要不然无法判断什么时候找到。

2.方向数组,leetcode走几步就看到一堆,算是基本操作3.二维变一维,一维变二维,小技巧4.在赋visited值时用前一个位置的visited的值

代码有注释

代码如下:

import java.util.*;

public class Rearrange{//双向BFS
public static String src_st;//九宫起点状态
public static String des_st;//九宫终点状态
public static Queue<String> queue =new ArrayDeque<>();
/**
 * 1.是否访问 2.起点或终点访问
 */
public static Map<String,Integer> visited=new HashMap<>();
public static Map<String,Integer> depth=new HashMap<>(); //搜索深度
public static int dict[][]={{0,-1},{0,1},{1,0},{-1,0}};//方向数组(左右上下遍历)
public static int bfs() {
    queue.add(src_st);
    queue.add(des_st);
    while (!queue.isEmpty()) {
        String first = queue.peek();
        queue.poll();
        int curX = 0, curY = 0;
        for (int i = 0; i < first.length(); i++) {//定位空格位置(句点)
            if (first.charAt(i) == '.') {
                curX = i / 3;
                curY = i % 3;
            }
        }
        int newX, newY;
        for (int i = 0; i < 4; i++) {//四处逃窜
            newX = dict[i][0] + curX;
            newY = dict[i][1] + curY;
            if (newX >= 0 && newX <= 2 && newY >= 0 && newY <= 2) {//判断边界条件
                String new_st = first;
                char curtemp = new_st.charAt(curX * 3 + curY);
                char newtemp = new_st.charAt(newX * 3 + newY);
               new_st=  new_st.replace(curtemp, '-');//字符串交换字符
               new_st= new_st.replace(newtemp, curtemp);
               new_st=new_st.replace('-', newtemp);
                if (!visited.containsKey(new_st)) {//没遍历过
                    visited.put(new_st, visited.get(first));
                    depth.put(new_st, depth.get(first) + 1);
                    queue.add(new_st);
                } else {
                    /**              2           4        3
                     * 遍历过了 1.起点回到起点 2.终点回到终点3.会和
                     */
                    if (visited.get(first) + visited.get(new_st) == 3) {
                        return  depth.get(first) + depth.get(new_st) + 1;
                    }
                }

            }
        }

    }
    return -1;
}

    public static void main(String[] args) {

        Scanner scanner=new Scanner(System.in);
        System.out.println("请输入九宫起点字符串:");
        src_st=scanner.next();
        System.out.println("请输入九宫终点字符串:");
        des_st=scanner.next();

      visited.put(src_st,1);
      visited.put(des_st,2);

        depth.put(src_st,0);
        depth.put(des_st,0);
        int n=bfs();
        System.out.println("九宫重排搜索次数:"+"\t"+n);
    }
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值