隐式图的搜索问题(九宫重排)——项目实现

隐式图的搜索问题(九宫重排)——项目实现

隐式图的搜索问题(九宫重排)——项目实现

源代码

package SearchPath;

public class test {
    public static void main(String[] args) {
        Database database = new Database();
        SearchPath searchPath = new SearchPath(database);
        searchPath.insertFirst();
    }
}

package SearchPath;

public class Node {

    private int status[];
    private int parent[];

    public int[] getParent() {
        return parent;
    }

    public void setParent(int[] parent) {
        this.parent = parent;
    }

    public int[] getStatus() {
        return status;
    }

    public void setStatus(int[] status) {
        this.status = status;
    }

    private int g;
    private int h;
    
    public void setH(int h) {
        this.h = h;
    }

    public int getG() {
        return g;
    }

    public void setG(int g) {
        this.g = g;
    }

    public int getF() {
        return g + h;
    }

}

package SearchPath;

import java.util.ArrayList;
import java.util.List;

public class Database {
    private List<Node> nodeList = new ArrayList<>();
    private List<Node> closeList = new ArrayList<>();
    private List<Node> changeList = new ArrayList<>();
    private List<Node> pathList = new ArrayList<Node>();

    public Database() {

    }

    public List<Node> getPathList() {
        return pathList;
    }

    public List<Node> getCloseList() {
        return closeList;
    }

    public List<Node> getOpenList() {
        return nodeList;
    }

    public List<Node> getChangeList() {
        return changeList;
    }
}

package SearchPath;

import java.util.Arrays;
import java.util.List;

public class NodeDao {
    private List<Node> openList;
    private List<Node> closeList;
    private List<Node> changeList;
    private List<Node> pathList;

    public List<Node> getPathList() {
        return pathList;
    }

    public List<Node> getOpenList() {
        return openList;
    }

    public NodeDao(Database database) {
        this.openList = database.getOpenList();
        this.closeList = database.getCloseList();
        this.changeList = database.getChangeList();
        this.pathList = database.getPathList();
    }

    /**
     * 写入open表
     * @return
     */
    public void insertOpenList(Node node) {
        openList.add(node);
    }

    /**
     * 写入close表
     */
    public void insertCloseList(Node node) {
        closeList.add(node);
        openList.remove(node);
    }

    /**
     * 对open表按f(n)由小到大排序
     */
    public void sort() {
        bubbleSort(openList);
    }

    /**
     *冒泡排序
     */
    public void bubbleSort(List<Node> list){
        for (int i = 0; i < list.size(); i++) {
            for (int j = 0; j < list.size() - i - 1; j++) {
                if (list.get(j).getF() > list.get(j + 1).getF()) {
                    Node temp = list.get(j);
                    list.set(j, list.get(j + 1));
                    list.set(j + 1, temp);
                }
            }
        }
    }

    /**
     * 判断是否已存储
     */
    public boolean judge(Node node) {
        boolean flag = false;
        for (int i = 0; i < openList.size(); i++) {
            if (Arrays.equals(openList.get(i).getStatus(), node.getStatus())) {
                flag = true;
            }
        }
        for (int i = 0; i < closeList.size(); i++) {
            if (closeList != null) {
                if (Arrays.equals(closeList.get(i).getStatus(), node.getStatus())) {
                    flag = true;
                }
            }
        }
        return flag;
    }

    /**
     * g(n)相同时,将f(n)较大值从open表中删除
     */
    public void delete() {
        for (int i = 0, j = openList.size() - 1; i < j; i++, j--) {
            if (openList.get(i).getG() == openList.get(j).getG()) {
                changeList.add(openList.get(i));
                changeList.add(openList.get(j));
            }
        }
        if (changeList.size() > 1) {
            bubbleSort(changeList);
            //由小到大排序 如果最小的有两个,则把其他的删了
            if (changeList.get(0).getF() == changeList.get(1).getF()) {
                for (int i = 2; i < changeList.size(); i++) {
                    openList.remove(changeList.get(i));
                    closeList.add(changeList.get(i));
                }
            } else {
                for (int i = 1; i < changeList.size(); i++) {
                    openList.remove(changeList.get(i));
                    closeList.add(changeList.get(i));
                }
            }
            for (int i = 0; i < changeList.size(); i++) {
                changeList.remove(i);
            }
        } else if (changeList.size() == 1) {
            openList.remove(changeList.get(0));
            closeList.remove(changeList.get(0));
            changeList.remove(0);
        }
    }

    /**
     * 通过数组找到该结点
     */
    public Node previous(int[] arr) {
        Node node = null;
            for (int i = 0; i < closeList.size(); i++) {
                if (Arrays.equals(closeList.get(i).getStatus(), arr)) {
                    node = closeList.get(i);
                    //保存至路径表,方便最后按顺序输出
                    pathList.add(node);
                }
            }
        return node;
    }
}

package SearchPath;

import java.util.Arrays;
import java.util.Scanner;

public class SearchPath {
    private NodeDao nodeDao;

    public SearchPath(Database database) {
        nodeDao = new NodeDao(database);
    }

    int[] start=new int[9];//{2, 5, 8, 3, 4, 6, 1, 7, 0};
    int[] target=new int[9];// {2, 8, 6, 3, 5, 0, 1, 4, 7};
    int g = 0;
    int flag = -1;
    /**
     * 将输入的数存入数组中
     */
    public void inputStart(){
        Scanner scanner=new Scanner(System.in);
        System.out.println("请输入初始状态:");
        for(int i=0;i<9;i++) {
            start[i] = scanner.nextInt();
        }
    }
    public void inputTarget(){
        Scanner scanner=new Scanner(System.in);
        System.out.println("请输入目标状态:");
        for(int i=0;i<9;i++) {
            target[i] = scanner.nextInt();
        }
    }

    /**
     * 将第一个结点写入open表,并进行第一次搜索、随之判断、再搜索、再判断
     */
    public void insertFirst() {
        inputStart();
        inputTarget();
        Node node = new Node();
        node.setStatus(start);
        node.setH(countH(start));
        node.setG(0);
        nodeDao.insertOpenList(node);
        g++;
        move(node);
        start();
    }

    /**
     * 根据不同的情况选择下一步进行扩展搜索的结点
     */
    public void start() {
        if (nodeDao.getOpenList().size() > 1) {
            if (nodeDao.getOpenList().get(0).getF() != nodeDao.getOpenList().get(1).getF()) {
                g++;
                move(nodeDao.getOpenList().get(0));
                nextSearch();
            } else {
                g++;
                move(nodeDao.getOpenList().get(0));
                move(nodeDao.getOpenList().get(1));
                nextSearch();
            }
        } else {
            g++;
            move(nodeDao.getOpenList().get(0));
            nextSearch();
        }
    }

    /**
     * 再次搜索与判断
     */
    public void nextSearch() {
        search();
        if (flag >= 0) {
            searchParent(nodeDao.getOpenList().get(flag));
            printLast();
        } else {
            //如果g(n)相同,则将f(n)较大的值从open表中删除,放入close表中
            nodeDao.delete();
            start();
        }
    }

    /**
     * 移动空格,产生新的结点
     */
    public void move(Node parent) {
        int zero = index(parent.getStatus());
        if (zero != 0 && zero != 3 && zero != 6) {
            //如果能左移,则进行左移创造新结点
            int[] A = parent.getStatus().clone();
            A[zero] = A[zero - 1];
            A[zero - 1] = 0;
            insertNew(parent, A);
        }
        if (zero != 2 && zero != 5 && zero != 8) {
            //如果能右移,则进行右移创造新节点
            int[] B = parent.getStatus().clone();
            B[zero] = B[zero + 1];
            B[zero + 1] = 0;
            insertNew(parent, B);
        }
        if (zero != 0 && zero != 1 && zero != 2) {
            //如果能上移,则进行上移创造新节点
            int[] C = parent.getStatus().clone();
            C[zero] = C[zero - 3];
            C[zero - 3] = 0;
            insertNew(parent, C);
        }
        if (zero != 6 && zero != 7 && zero != 8) {
            //如果能下移,则进行下移创造新节点
            int[] D = parent.getStatus().clone();
            D[zero] = D[zero + 3];
            D[zero + 3] = 0;
            insertNew(parent, D);
        }
        //将父节点存入close表,并从open表中删除
        nodeDao.insertCloseList(parent);
        nodeDao.sort();
    }

    /**
     * 根据情况将新结点加入open表
     */
    public void insertNew(Node parent, int[] arr) {
        Node node = new Node();
        node.setStatus(arr);
        node.setG(g);
        node.setH(countH(arr));
        node.setParent(parent.getStatus().clone());
        if (!nodeDao.judge(node)) {
            nodeDao.insertOpenList(node);
        }
    }

    /**
     * 计算h(n)
     */
    public int countH(int[] arr) {
        int flag = 0;
        for (int i = 0; i < 9; i++) {
            if (arr[i] != target[i]) {
                flag++;
            }
        }
        return flag;
    }

    /**
     * 空格即零所在的位置
     */
    public int index(int[] now) {
        int index = -1;
        for (int i = 0; i < 9; i++) {
            if (0 == now[i]) {
                index = i;
            }
        }
        return index;
    }

    /**
     * 循环找到父结点,存入pathList
     */
    public void searchParent(Node targetNode) {
        if (targetNode.getParent() != null) {
            int[] result = targetNode.getParent();
                //通过数组找到该结点,存入pathList
                searchParent(nodeDao.previous(result));
        }
    }

    /**
     * 判断openList中是否已有目标节点
     */
    public void search() {
        for (int i = 0; i < nodeDao.getOpenList().size(); i++) {
            if (Arrays.equals(target, nodeDao.getOpenList().get(i).getStatus())) {
                flag = i;
            }
        }
    }


    /**
     * 按顺序打印路径
     */
    public void printLast() {
        System.out.println("最短路径如下:");
        int number = 0;
        for (int i = nodeDao.getPathList().size() - 1; i >= 0; i--) {
            int count = 0;
            int[] result = nodeDao.getPathList().get(i).getStatus();
            for (int j = 0; j < 9; j++) {
                count++;
                printOrder(result, count, j);
            }
            System.out.println("------------");
            number++;
        }
        for (int i = 0; i < target.length; i++) {
            flag++;
            printOrder(target, flag, i);
        }
        System.out.println("------------");
        System.out.println("一共需要走 " + number + "步 达成目标");
    }

    /**
     * 打印输出
     */
    public void printOrder(int[] arr, int tab, int index) {
        System.out.print(arr[index] + " ");
        if (tab % 3 == 0) {
            System.out.println(" ");
        }
    }
}



运行结果

在这里插入图片描述
在这里插入图片描述
2021.3.15修改:可输入初始状态和目标状态数组。

在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
隐式欧拉法(Implicit Euler Method)是一种常用的数值求解常微分方程的方法,可以用于求解一阶或高阶的常微分方程。下面是使用MATLAB实现隐式欧拉法的步骤: 1. 定义微分方程:首先需要定义待求解的微分方程。例如,假设我们要求解一阶常微分方程dy/dt = f(t, y),其中f(t, y)是关于t和y的函数。 2. 离散化时间:将求解区间[t0, tn]等分为N个小区间,步长为h = (tn - t0) / N。定义时间网格t = [t0, t1, ..., tn],其中ti = t0 + i * h。 3. 初始化:给定初始条件y0,将y0作为初始值。 4. 迭代求解:对于每个时间步i = 1, 2, ..., N,进行以下步骤: - 定义隐式方程:根据隐式欧拉法的公式,得到隐式方程yi - y(i-1) - h * f(ti, yi) = 0。 - 解隐式方程:使用MATLAB的数值求解函数(如fsolve)求解上述隐式方程,得到yi。 - 更新时间和解:更新时间ti+1 = ti + h,并将求得的yi作为下一个时间步的初始值。 5. 输出结果:得到离散化的时间网格和对应的解y。 下面是一个MATLAB代码示例,演示如何使用隐式欧拉法求解一阶常微分方程dy/dt = -2 * t * y,初始条件为y(0) = 1,在区间[0, 1]上进行求解: ```matlab % 定义微分方程 f = @(t, y) -2 * t * y; % 定义求解区间和步长 t0 = 0; tn = 1; N = 100; h = (tn - t0) / N; % 初始化 t = zeros(N+1, 1); y = zeros(N+1, 1); t(1) = t0; y(1) = 1; % 迭代求解 for i = 2:N+1 % 定义隐式方程 implicit_eqn = @(x) x - y(i-1) - h * f(t(i-1), x); % 解隐式方程 y(i) = fsolve(implicit_eqn, y(i-1)); % 更新时间 t(i) = t(i-1) + h; end % 输出结果 plot(t, y); xlabel('t'); ylabel('y'); title('Solution of dy/dt = -2 * t * y'); ``` 希望以上内容对你有所帮助!如果有任何问题,请随时提问。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值