15-谜问题(深拷贝、LC检索、面向对象编程)
在一个分成16格的方形棋盘上,放有15块编了号码的牌。对这些牌给定一种初始排列,要求通过一系列的合法移动将这一初始排列转换成目标排列。
这个问题解决时用到了L-C检索。在检索的过程中计算估值函数c(x)=f(x)+g(x);
通过比较估值函数确定遍历的方向。L-C检索是有智力的搜索。
package lc_search;
public class Riddle_15 {
    Riddle_15(){}
    public class A implements Cloneable{ //棋盘的抽象类
        private int[][] a;//棋盘数组
        private int x;//空格所在x坐标
        private int y;//空格所在y坐标
        A(){
            int[][] b = { //棋盘
                    {5,1,2,4},
                    {0,6,3,8},
                    {9,10,7,11},
                    {13,14,15,12}
            };
            a = b;
            for(int i=0;i<4;i++){
                for(int j=0;j<4;j++){
                    if(a[i][j] == 0){
                        x = i;
                        y = j;
                    }
                }
            }
        }
        public void show(){//打印棋盘
            System.out.println("---------------------------------");
            for (int i = 0; i < 4; i++) {
                for (int j = 0; j < 4; j++) {
                    if(a[i][j] == 0)
                        System.out.print("|"+" "+"\t");
                    else
                        System.out.print("|"+a[i][j]+"\t");
                }
                System.out.println("|");
                System.out.println("---------------------------------");
            }
        }
        public void set(int x,int y){//移动空格
            if(Math.abs(x)>1||Math.abs(y)>1){
                System.out.println("-1");
                return;
            }
            x = this.x + x;
            y = this.y + y;
            if (x < 0 || x >= 4 || y < 0
                    || y >= 4) {// 检测能否朝某个方面移动
                return;
            } else {// 移动
                a[this.x][this.y] = a[x][y];
                a[x][y] = 0;
                this.x = x;
                this.y = y;
            }
        }
        public Boolean test(){//开局判断棋盘是否可解
            int x = (this.x+this.y)%2 ;//空格初始位置决定
            int count = 0;
            a[this.x][this.y] = 16;//对空格需要做一定的处理Position[空格] = 16
            for(int i=0;i<4;i++){
                for(int j=0;j<4;j++){
                    //if(a[i][j] == 0)//排除空格这一异常点
                    //    continue L1;
                    for(int k=j+1;k<4;k++){//处理本行未完元素
                        if(a[i][k]<a[i][j])
                            count++;
                    }
                    for(int k=i+1;k<4;k++){//处理接下来的几行
                        for(int l=0;l<4;l++){
                            if(a[k][l]<a[i][j])
                                count++;
                        }
                    }
                }
            }
            a[this.x][this.y] = 0;
            if((count+x)%2 == 1){
                System.out.println("目标不可达!"+(count+x));
                return false;
            }
            //System.out.println("test");
            return true;
        }
        public int g(){//估值函数
            int g = 0;
            for (int i = 0; i < 4; i++) {
                for (int j = 0; j < 4; j++) {
                    if (a[i][j] != i * 4 + j + 1)
                        g++;
                }
            }
            return g-1;
        }
        public Object clone() throws CloneNotSupportedException{//数组需要深拷贝
            A a = (A)super.clone();
            //b.show();
            a.a = new int[4][4];
            for(int i=0;i<4;i++){//数组克隆在每一行都要操作
                a.a[i] = this.a[i].clone();//注意此处要用到this指针
            }
            return a;
        }
    }
    public void test() throws CloneNotSupportedException{//测试深度拷贝是否成功
        A a = new A();
        a.show();
        A b = (A)a.clone();
        b.show();
        a.set(1,0);
        b.show();
    }
    public void search() throws CloneNotSupportedException{//检索函数
        A a = new A();//用于存放E节点(当前处理节点)
        if(!a.test()){
            return;
        }
        A aa = new A();//用于存放极优节点
        A aaa = new A();//用与存放父节点
        aa = (A) a.clone();
        int f = 0;// c = f(x) + g(x);
        int g=1000;
        int c=0;
        int min=10000;
        while (g != 0) {
            //System.out.println("aa[][]极优节点:g="+g );
            //aa.show();
            int[] row = {  - 1, 0, 0,  1 };
            int[] column = { 0, - 1,  1, 0 };
            min = 1000;
            f++;
            aaa =(A) a.clone();
            //System.out.println("原棋盘:" );
            aaa.show();
            System.out.println();
            for (int k = 0; k < 4; k++) {//
                a.set(row[k], column[k]);
                g = a.g();
                c = f + g ;
                //System.out.println("a[][]当前处理节点:");
                //a.show();
                if (c < min) {
                    min = c;
                    aa = (A)a.clone();
                }
                a = (A)aaa.clone();
                //System.out.println("a[][]原始棋盘:");
                //aaa.show();
                //a.show();
            }
            a = (A)aa.clone();
        }
        aa.show();
        System.out.println("ok");
    }
    public static void main(String[] args) throws Exception {
        // TODO Auto-generated method stub
        Riddle_15 r = new Riddle_15();
        r.search();
        //r.test();
        return;
    }
}

15-谜问题详细介绍:




15-谜问题(深拷贝、LC检索、面向对象编程)的更多相关文章
- [.net 面向对象编程基础] (15) 抽象类
		
[.net 面向对象编程基础] (15) 抽象类 前面我们已经使用到了虚方法(使用 Virtual修饰符)和抽象类及抽象方法(使用abstract修饰符)我们在多态一节中说到要实现类成员的重写必须定义 ...
 - Javascript面向对象编程(三):非构造函数的继承(对象的深拷贝与浅拷贝)
		
Javascript面向对象编程(三):非构造函数的继承 作者: 阮一峰 日期: 2010年5月24日 这个系列的第一部分介绍了"封装",第二部分介绍了使用构造函数实现&quo ...
 - python学习笔记15(面向对象编程)
		
虽然Python是解释性语言,但是它是面向对象的,能够进行对象编程. 一.如何定义一个类 在进行python面向对象编程之前,先来了解几个术语:类,类对象,实例对象,属性,函数和方法. 类是对现实世界 ...
 - [.net 面向对象编程基础] (20)  LINQ使用
		
[.net 面向对象编程基础] (20) LINQ使用 通过上节LINQ的基础知识的学习,我们可以开始使用LINQ来进行内存数据的查询了,我们上节说了LINQ的定义为:Language Integr ...
 - 从一些简单代码实例彻底理解面向对象编程思想|OOP本质是什么?
		
从Rob Pike 的 Google+上的一个推看到了一篇叫<Understanding Object Oriented Programming>的文章,我先把这篇文章简述一下,然后再说说 ...
 - 《Java面向对象编程》
		
<Java面向对象编程> 第11章 对象的生命周期 11.1 创建对象的方式 用new语句创建对象 运用反射手段,调用java.lang.Class 或者 java.lang.Const ...
 - [.net 面向对象编程基础]  (1)  开篇
		
[.net 面向对象编程基础] (1)开篇 使用.net进行面向对象编程也有好长一段时间了,整天都忙于赶项目,完成项目任务之中.最近偶有闲暇,看了项目组中的同学写的代码,感慨颇深.感觉除了定义个类,就 ...
 - 深入理解javascript中实现面向对象编程方法
		
介绍Javascript中面向对象编程思想之前,需要对以下几个概念有了解: 1. 浅拷贝和深拷贝:程序在运行过程中使用的变量有在栈上的变量和在堆上的变量,在对象或者变量的赋值操作过程中,大多数情况先是 ...
 - [.net 面向对象编程基础] (3) 基础中的基础——数据类型
		
[.net 面向对象编程基础] (3) 基础中的基础——数据类型 关于数据类型,这是基础中的基础. 基础..基础..基础.基本功必须要扎实. 首先,从使用电脑开始,再到编程,电脑要存储数据,就要按类型 ...
 
随机推荐
- intellij springmvc的配置文件报错
			
报错: Checks references injected by IntelliLang plugin. Cannot resolve bean 解决: File--Settings[或直接CTR ...
 - SVN使用基础
			
1.安装svn centos:yum install subversion -y ubuntu:apt-get install subversion -y 2.创建库目录 mkdir /opt/.sv ...
 - linux_思想
			
linux有哪些重要的思想? 1. 做的越多错的越多 2. 纸包不住火 3. 操作重要文件前备份,操作后查看结果 4. 看到命令输出结果,可能命令有个选择直接获得对应值 5. 先定行,再定列
 - CSS学习(一)
			
/*</br> * color</br> * background-color background-image background-repeat background-po ...
 - junit--eclipse插件
			
现在比较火的IDE是JIDE,但是我一直在使用eclipse.对eclipse比较熟悉了,也有了感情了.这里就以eclipse为例,来整理下eclipse中junit插件的使用. 添加junit包到自 ...
 - 如何更改wampserver的网站根目录
			
我之前把网站根目录自定义为:D:/demo,现在想改为:D:www, 过程就是打开httpd.conf文件,搜索demo,然后把demo改为www,之后更改虚拟配置文件,记住D盘下一定要有www目录 ...
 - GO开发:用go写个日志监控系统
			
日志收集系统架构 1.项目背景 a. 每个系统都有日志,当系统出现问题时,需要通过日志解决问题 b. 当系统机器比较少时,登陆到服务器上查看即可满足 c. 当系统机器规模巨大,登陆到机器上查看几乎不现 ...
 - 什么是<!DOCTYPE html>
			
什么是<!DOCTYPE html>? 在HTML文档初,往往会有这么一句话<!DOCTYPE html>,那么它的意义是什么呢?它是html5标准网页声明,全称为Docume ...
 - Servlet第六篇【Session介绍、API、生命周期、应用、与Cookie区别】
			
什么是Session Session 是另一种记录浏览器状态的机制.不同的是Cookie保存在浏览器中,Session保存在服务器中.用户使用浏览器访问服务器的时候,服务器把用户的信息以某种的形式记录 ...
 - SQL Server比较2table字段的差异
			
由于项目前后用了2个数据库,需要统计数据库结构的变化,需要统计每个表的变化,由于人工核对挺浪费时间,就写了一点代码: 1.统计表的字段数量(查询表有多少列): select count(name) ...