• codevs1225 八数码难题


    题目描述 Description

    Yours和zero在研究A*启发式算法.拿到一道经典的A*问题,但是他们不会做,请你帮他们.
    问题描述

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

    输入描述 Input Description

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

    输出描述 Output Description

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

    样例输入 Sample Input

    283104765

    样例输出 Sample Output

    4

    正解:BFS+hash

    解题报告:

      向总让我写标程,然后我就愉快地开始写这道最初学搜索时的水题,然而我第一遍wa了,mdzz

      hash判重,BFS搜索
     
     1 #include <iostream>
     2 #include <cstdlib>
     3 #include <cstring>
     4 #include <cstdio>
     5 #include <cmath>
     6 #include <algorithm>
     7 using namespace std;
     8 typedef long long LL;
     9 const int MOD = 1000007;//hash的模
    10 char ch[12];
    11 int now;
    12 int a[100001][10];//记录状态
    13 int times[100001];//计算移动次数
    14 int final[10]={1,2,3,8,0,4,7,6,5};//目标局面
    15 int cnt,hash[1000008],next[100001],to[100001];//hash表
    16 
    17 void insert(int x){//插入哈希表
    18     int num=0;
    19     for(int i=0;i<9;i++) num=num*9+a[x][i];
    20     int ha=num%MOD;
    21     next[++cnt]=hash[ha]; hash[ha]=cnt; to[cnt]=num;
    22 }
    23 
    24 bool check(int x){//哈希判重,挂链
    25     int num=0;
    26     for(int i=0;i<9;i++) num=num*9+a[x][i];
    27     int ha=num%MOD;
    28     for(int i=hash[ha];i;i=next[i]) 
    29     if(to[i]==num) return false;
    30     return true;
    31 }
    32 
    33 int main()
    34 {
    35   for(int i=0;i<9;i++) ch[i]=getchar();
    36   for(int i=0;i<9;i++) a[1][i]=ch[i]-'0';
    37   int head=0,tail=1; insert(1);
    38   while(head<tail) {
    39       head++;
    40       for(int i=0;i<9;i++) if(a[head][i]==0) { now=i; break; }//找到当前0的位置
    41       for(int k=-3;k<=3;k+=2) {//枚举移动的每一种可能
    42       int to=now+k;
    43       if(to<0 || to>=9) continue;//越界
    44       if(now%3==2 && k==1) continue;//在右边界上不能再向右移动一格
    45       if(now%3==0 && k==-1) continue;//在左边界不能再向左移动一格
    46       tail++;  for(int i=0;i<9;i++) a[tail][i]=a[head][i];//把交换前的情况复制到新数组
    47       swap(a[tail][now],a[tail][to]);//交换位置
    48       if(check(tail)) {//得到一组可行解
    49           times[tail]=times[head]+1;
    50           bool ok=true;
    51           for(int i=0;i<9;i++) if(a[tail][i]!=final[i]) { ok=false; break; }
    52           if(ok) { printf("%d",times[tail]); return 0; }
    53           insert(tail);     
    54       }
    55       else tail--;//此状态已经重复,可以省略
    56       }
    57   }
    58   return 0;
    59 }
  • 相关阅读:
    ORA-00119: invalid specification for system parameter LOCAL_LISTENER
    local_listener参数的作用!
    DDL为什么不能rollback?
    LGWR和DBWn的触发条件
    修改spfile位置
    初识oracle重做日志文件
    ORACLE AUDIT 审计
    Oracle SQL_TRACE使用小结
    Web API(六):使用Autofac实现依赖注入
    JavaScript:属性的操作
  • 原文地址:https://www.cnblogs.com/ljh2000-jump/p/5677133.html
Copyright © 2020-2023  润新知