zoukankan      html  css  js  c++  java
  • 八数码难题(luogu 1379)

    题目描述

    在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字。棋盘中留有一个空格,空格用0来表示。空格周围的棋子可以移到空格中。要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765),找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变。

    输入输出格式

    输入格式:

     

    输入初始状态,一行九个数字,空格用0表示

     

    输出格式:

     

    只有一行,该行只有一个数字,表示从初始状态到目标状态需要的最少移动次数(测试数据中无特殊无法到达目标状态数据)

     

    输入样例
    283104765
    
    输出样例
    4

    这是 alphar 学长带我入门广搜的例题,当时完全是抄代码,因为完全没有代码功力

    当时把 codevs 的题目A掉了,现在偶然见到 luogu 有人求助这道题目,点开一看,又是不一样的方法

    思路:

    这道题目关键在于判重,因为如果只是一个简单的搜索,它只会是瞎跑,杂乱无章,我们要做的就是规定它向着什么方向跑,以及不让他走了半天又绕回原地

    于是就有了A*算法的思路

    构造一个估价函数,其实说白了就是看他离终点还差多远

    通过迭代加深的方法,如果当前状态可以到达终点,我们就继续往下走

    至于估价函数……意会就好,无需证明

    code

    #include<stdio.h> 
    #include<algorithm> 
    using namespace std;
    bool flag;
    int k,sx,sy,mp[5][5];
    int plan[5][5]={{1,2,3},{8,0,4},{7,6,5}};
    int dx[]={1,0,0,-1};
    int dy[]={0,1,-1,0};
    
    bool check() 
    {
        for(int i=0;i<3;i++) 
            for(int j=0;j<3;j++) 
                if(plan[i][j]!=mp[i][j]) return false;
        return true;
    }
    
    bool test(int stp) {
        int cnt=0;
        for(int i=0;i<3;++i)
            for(int j=0;j<3;++j) 
                if(mp[i][j]!=plan[i][j]) if(++cnt+stp>k) return false;
        return true;
    }
    
    void star(int x,int y,int stp,int last) 
    {
        if(stp==k) {
            if(check()) flag=1;
            return;
        } 
        if(flag) return;
        for(int i=0;i<4;++i) {
            int nx=x+dx[i],ny=y+dy[i];
            if(nx<0 || ny<0 || nx>2 || ny>2 || last+i==3) continue;
            swap(mp[x][y],mp[nx][ny]);
            if(test(stp)) star(nx,ny,stp+1,i);
            swap(mp[x][y],mp[nx][ny]);
        }
    }
    
    int main()
    {
        for(int i=0;i<=2;i++) 
            for(int j=0;j<=2;j++) {
                char c;
                scanf("%c",&c);
                mp[i][j]=c-'0';
                if(mp[i][j]==0) sx=i,sy=j;     
            }
        if(check()) {
            printf("0");return 0;
        }
        while(++k) {
            star(sx,sy,0,-1);
            if(flag) {
                printf("%d",k);
                break;
            }
        }
        return 0;
    }
  • 相关阅读:
    android 75 新闻列表页面
    android 74 下载文本
    android 73 下载图片
    android 72 确定取消对话框,单选对话框,多选对话框
    android 71 ArrayAdapter和SimpleAdapter
    android 70 使用ListView把数据显示至屏幕
    maven如何将本地jar安装到本地仓库
    Centos6.7搭建ISCSI存储服务器
    解决maven打包编译出现File encoding has not been set问题
    MySQL 解决 emoji表情 的方法,使用utf8mb4 字符集(4字节 UTF-8 Unicode 编码)
  • 原文地址:https://www.cnblogs.com/qseer/p/9862387.html
Copyright © 2011-2022 走看看