zoukankan      html  css  js  c++  java
  • luoguP1379 八数码难题[启发式搜索]

    题目描述

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

    输入输出格式

    输入格式:

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

    输出格式:

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

    输入输出样例

    输入样例#1:
    283104765
    
    输出样例#1:
    4

    
    
     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 #include<cmath>
     5 using namespace std;
     6 
     7 //目标态 
     8 int fin[9][2]={{1,1},{0,0},{0,1},{0,2},{1,2},{2,2},{2,1},{2,0},{1,0}};
     9 
    10 struct State{
    11     int a[3][3];
    12 };
    13 
    14 int lim=0,ok;
    15 
    16 //计算f(n)函数 
    17 int H(const State &st){
    18     int ret=0;
    19     for(int i=0;i<3;i++)
    20         for(int j=0;j<3;j++){
    21             int t=st.a[i][j];
    22             if(t)  ret+=abs(fin[t][0]-i)+abs(fin[t][1]-j);
    23         }
    24     return ret;
    25 }
    26 
    27 void dfs(State st,int g){
    28     int h=H(st);
    29     if(ok||g+h>lim)
    30         return;
    31     if(!h){
    32         ok=1;
    33         return;
    34     }
    35     int x,y;
    36     for(int i=0;i<3;i++)
    37         for(int j=0;j<3;j++)
    38             if(!st.a[i][j]){
    39                 x=i,y=j;
    40                 break;
    41             }
    42     if(x>0){
    43         swap(st.a[x][y],st.a[x-1][y]);
    44         dfs(st,g+1);
    45         swap(st.a[x][y],st.a[x-1][y]);
    46     }
    47     if(x<2){
    48         swap(st.a[x][y],st.a[x+1][y]);
    49         dfs(st,g+1);
    50         swap(st.a[x][y],st.a[x+1][y]);
    51     }
    52     if(y>0){
    53         swap(st.a[x][y],st.a[x][y-1]);
    54         dfs(st,g+1);
    55         swap(st.a[x][y],st.a[x][y-1]);
    56     }
    57     if(y<2){
    58         swap(st.a[x][y],st.a[x][y+1]);
    59         dfs(st,g+1);
    60         swap(st.a[x][y],st.a[x][y+1]);
    61     }
    62 }
    63 
    64 int main(){
    65     State st;
    66     char ch[10];
    67     scanf("%s",ch);
    68     for(int i=0;i<3;i++)
    69         for(int j=0;j<3;j++)
    70             st.a[i][j]=ch[i*3+j]-'0';
    71     while(++lim){
    72         dfs(st,0);
    73         if(ok)  break;
    74     }
    75     printf("%d
    ",lim);
    76     return 0;
    77 }

    在写盲目bfs 1590ms 后很久才用的IDA*解法
    感谢will7101在luogu上题解给本蒟蒻此题IDA*稍短代码的启蒙
    终于学会了计算h(n)    QwQ
     

    总是在梦里我看到你无助的双眼  我的心又一次被唤醒
    
    
  • 相关阅读:
    打jar包的命令
    WebServiceWSDLWeb
    linux命令之检测端口是否启用
    mybatis generator 插件安装及使用
    Mybatis 中一对多,多对一的配置
    大数据时代日志分析平台ELK的搭建
    关于RestfulAPI与SpringMVC之间的传值
    linux快速清空文件内容
    Linux之第一个shell命令
    Linux之yum
  • 原文地址:https://www.cnblogs.com/ZYBGMZL/p/6852733.html
Copyright © 2011-2022 走看看