人工智能实验一--八数码问题

人工智能实验一,任课老师申冬苏。

 

 

 

个人总结:一个很简单的BFS问题,其他另外的算法可以自己尝试,这里只给最简单的BFS算法。 

下面是八数码的类,使用的是JAVA语言:
实现过程很简单,定义方向链表,然后0-4下标表示左上右下四方向,不能往回走。
因此只需要方向下标相减不等于2即可,然后用结构体保存方向,路径等。

package Solutions.Homework;

import StructNode.MyTuple;

import java.util.*;

public class EightDigital {
    //数码运动的方向
    //the directions of number
    public List<int[]>dir = new ArrayList<>();
    private String ans = "";
    private char[][] ep;
    public EightDigital(){
        dir.add(new int[]{0, -1});
        dir.add(new int[]{-1, 0});
        dir.add(new int[]{0, 1});
        dir.add(new int[]{1, 0});
    }
    public String path(String[] source, String[] dest){
        int n = source.length, m = source[0].length();
        this.ep = new char[n][m];
        char[][] p = new char[n][m];
        //data initialization
        for(int i = 0;i < n; i++){
            p[i] = source[i].toCharArray();
            this.ep[i] = dest[i].toCharArray();
        }
        //to decide whether it is reachable
        System.out.println("source:" + Arrays.deepToString(p));
        System.out.println("dest:  " + Arrays.deepToString(ep));
        if(!isArrived(source, dest)) return "No Way From Source to Dest";

        for(int i = 0; i < n;i++){
            for(int j = 0; j < m;j++){
                if(p[i][j] == '0'){
                    //开始搜索
                    //start find answer
                    bfs(p, i, j, n, m);
                    break;
                }
        }
        }
        return ans;
    }
    /*
    * input:数码的二维数组,开始搜索的坐标点,以及长度
    * progress:使用广度优先搜索搜索能够实现的路径
    * */
    private void bfs(char[][] p, int x, int y, int n, int m){
        //bfs使用队列,tuple包含坐标,上次经过的方向,路径,以及对应的数码。
        //bfs need queue, the tuple contains points, last direction, path, and the corresponding number
        Deque<MyTuple<int[], String, char[][]>>dq = new ArrayDeque<>();
        dq.addLast(new MyTuple<>(new int[]{x, y ,-10}, "", p));
        while(!dq.isEmpty()){
            var t = dq.pollFirst();
            //满足条件即可跳出循环
            //if we look for the answer
            if(Arrays.deepEquals(t.getThird(), ep)){
                ans = t.getSecond();
                System.out.println(ans.length());
                break;
            }
            for(int i = 0;i < dir.size();i++){
                //不能往返回的方向跑
                //prohibit to go back
                if(Math.abs(t.getFirst()[2] - i) == 2) continue;
                int xi = t.getFirst()[0] + dir.get(i)[0], yi = t.getFirst()[1] + dir.get(i)[1];
                //不能越界
                //prohibit out of the verge
                if(xi < 0 || xi >= n || yi < 0 || yi >= m) continue;
                //System.out.println(t.getFirst()[0]+" "+xi+" "+t.getFirst()[1]+" "+yi);
                //时刻交换数码的值
                //swap the value of number all the time
                char[][] k = getP(t.getThird(), n, m);
                var temp = k[t.getFirst()[0]][t.getFirst()[1]];
                k[t.getFirst()[0]][t.getFirst()[1]] = k[xi][yi];
                k[xi][yi] = temp;
                dq.addLast(new MyTuple<>(new int[]{xi, yi, i}, t.getSecond() + String.valueOf(i), k));
            }
        }
    }
    /*
    * 复制一个中间变量,防止引用
    * */
    private char[][] getP(char[][] p, int n, int m){
        char[][] k = new char[n][m];
        //copy an obj to using
        for(int i = 0;i < n;i++){
            System.arraycopy(p[i], 0, k[i], 0, m);
        }
        return k;
    }
    private boolean isArrived(String[] source, String[] dest){
        StringBuilder s = new StringBuilder();
        StringBuilder d = new StringBuilder();
        for(int i = 0;i < source.length;i++){
            s.append(source[i]);
            d.append(dest[i]);
        }
        int cnts = 0, cntd = 0;
        //使用实验指导书上的方法判断是否可达
        //to decide whether it is reachable by formula.
        for(int i = 0;i < s.length();i++){
            for(int j = i - 1 ;j >= 0;j--){
                if(s.charAt(j) == '0' || d.charAt(j) == '0') continue;
                cnts = s.charAt(j) < s.charAt(i) ? cnts : cnts + 1;
                cntd = d.charAt(j) < d.charAt(i) ? cntd : cntd + 1;
            }
        }
        return (cntd & 1) == (cnts & 1);
    }
}

结构体的类:

package StructNode;

public class MyTuple<A, B, C> {
    private A first;
    private B second;

    private C third;
    public MyTuple(A first, B second, C third) {
        this.first = first;
        this.second = second;
        this.third = third;
    }

    public A getFirst() {
        return first;
    }

    public B getSecond() {
        return second;
    }
    public C getThird() {
        return third;
    }

    public void setFirst(A first) {
        this.first = first;
    }

    public void setSecond(B second) {
        this.second = second;
    }
    public void setThird(C third) {
        this.third = third;
    }
}

使用如下:

package org.example;

import Solutions.BPFace.BTTrain;
import Solutions.Homework.EightDigital;

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        EightDigital eightDigital = new EightDigital();
        String[] dest = new String[3];
        String[] source = new String[3];
        for(int i = 0;i < 3;i++){
            dest[i] = scanner.next();
        }
        for(int i = 0;i < 3;i++){
            source[i] = scanner.next();
        }
       System.out.println(eightDigital.path(dest, source));
    }
}

运行结果如下:

 可以看到需要28步,下面字符串就是路径,路径0-4表示左上右下。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值