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;
    }
  • 相关阅读:
    Qt之QLabel
    在Servlet中使用spring注入的bean
    Matlab中图片保存的5种方法
    LATEX中优化问题如何排列Max——s.t.格式
    Latex 初学者入门(四)-- 多个作者共享同一个地址
    一份不太简短的LaTeX教程 lshort – A short in­tro­duc­tion to LATEX 2elshort – A short in­tro­duc­tion to LATEX 2e
    LaTeX技巧:LaTeX括号总结
    Bibtex使用方法
    Latex初学者入门(三)-- 用BibTeX生成参考文献
    LaTeX之参考文献的写法
  • 原文地址:https://www.cnblogs.com/qseer/p/9862387.html
Copyright © 2011-2022 走看看