zoukankan      html  css  js  c++  java
  • 八数码问题

    有许多问题都可以转化为图的遍历的问题,但是之前我们做的题目的图要么是一开始就根据题意建立起来然后去遍历或者更加简单题目直接给你。

    但是类似于八数码问题它的图并不是一开始给你的,而是由程序动态生成的,称为隐式图。我们需要找到一个符合条件的终止路径

     

    八数码问题

    编号为 1~8 的 8个正方形滑块被摆成3行3列(有一个格子空留)。每次可以把与空格相邻的滑块(有公共边才算相邻)移到空格中,而它原来的位置就称为了
    新的空格。给定初始局面和目标局面( 用0表示空格格 ),你的任务是计算出最少的移动步数。 如果无法达到目标局面,则输 -1 
     
     

    分析:

    既然是要找到最少的移动步数,那么很容易去想到利用 BFS 进行搜索,但是最主要的问题是 这个涉及到隐式图的遍历,如何去记录隐式图以及如何去避免重复的搜索

    根据紫书上的建议有两种比较常用:

    1、直接采用STL里面的 set 进行去重

    2、采用 hash 表的方式

    STL的方式:

     1 #include <iostream>
     2 #include <algorithm>
     3 #include <string>
     4 #include <string.h>
     5 #include <vector>
     6 #include <map>
     7 #include <stack>
     8 #include <set>
     9 #include <queue>
    10 #include <math.h>
    11 #include <time.h>
    12 
    13 #define LL long long
    14 #define INF 0x3f3f3f3f
    15 #define ls nod<<1
    16 #define rs (nod<<1)+1
    17 
    18 const int maxn = 1e6 + 10;
    19 const LL MOD = 1e9 + 7;
    20 
    21 typedef int State[9];
    22 State st[maxn],goal;
    23 int dis[maxn];
    24 
    25 int dx[] = {-1,1,0,0};
    26 int dy[] = {0,0,-1,1};
    27 
    28 std::set<int> vis;
    29 
    30 
    31 void init_lookup_table() {
    32     vis.clear();
    33 }
    34 
    35 int try_to_insert(int s) {
    36     int v = 0;
    37     for (int i = 0;i < 9;i++)
    38         v = v * 10 + st[s][i];
    39     if (vis.count(v))
    40         return 0;
    41     vis.insert(v);
    42     return 1;
    43 }
    44 
    45 int bfs() {
    46     init_lookup_table();
    47     int front = 1,rear = 2;
    48     while (front < rear) {
    49         State &s = st[front];
    50         if (memcmp(goal,s, sizeof(s)) == 0) {
    51             return front;
    52         }
    53         int z;
    54         for (z = 0;z < 9;z++) {
    55             if (!s[z])
    56                 break;
    57         }
    58         int x = z / 3,y = z % 3;
    59         for (int d = 0;d < 4;d++) {
    60             int newx = x + dx[d];
    61             int newy = y + dy[d];
    62             int newz = newx * 3  +newy;
    63             if (newx >= 0 && newx < 3 && newy >= 0 && newy < 3) {
    64                 State &t = st[rear];
    65                 memcpy(&t,&s, sizeof(s));
    66                 t[newz] = s[z];
    67                 t[z] = s[newz];
    68                 dis[rear] = dis[front] + 1;
    69                 if (try_to_insert(rear))
    70                     rear++;
    71             }
    72         }
    73         front++;
    74     }
    75     return 0;
    76 }
    77 
    78 
    79 int main() {
    80     int t;
    81     scanf("%d",&t);
    82     while (t--) {
    83         for (int i = 0; i < 9; i++) {
    84             scanf("%d", &st[1][i]);
    85         }
    86         for (int i = 0; i < 9; i++)
    87             scanf("%d", &goal[i]);
    88         int ans = bfs();
    89         if (ans > 0)
    90             printf("%d
    ", dis[ans]);
    91         else
    92             printf("-1
    ");
    93     }
    94     return 0;
    95 }
    Ackerman

    hash表的方式:

      1 #include <iostream>
      2 #include <algorithm>
      3 #include <string>
      4 #include <string.h>
      5 #include <vector>
      6 #include <map>
      7 #include <stack>
      8 #include <set>
      9 #include <queue>
     10 #include <math.h>
     11 #include <cstdio>
     12 #include <time.h>
     13 
     14 #define LL long long
     15 #define INF 0x3f3f3f3f
     16 #define ls nod<<1
     17 #define rs (nod<<1)+1
     18 
     19 const int maxn = 4e5 + 10;
     20 const LL MOD = 1e9 + 7;
     21 
     22 const int hashsize = 1000003;
     23 typedef int State[9];
     24 State st[maxn],goal;
     25 int head[hashsize],Next[maxn];
     26 int dis[maxn];
     27 
     28 int dx[] = {-1,1,0,0};
     29 int dy[] = {0,0,-1,1};
     30 
     31 void init_lookup_table() {
     32     memset(head,0, sizeof(head));
     33 }
     34 
     35 int hash(State &s) {
     36     int v = 0;
     37     for (int i = 0;i < 9;i++)
     38         v = v * 10 + s[i];
     39     return v % hashsize;
     40 }
     41 
     42 int try_to_insert(int s) {
     43     int h = hash(st[s]);
     44     int u = head[h];
     45     while (u) {
     46         if (memcmp(st[u],st[s], sizeof(st[s])) == 0)
     47             return 0;
     48         u = Next[u];
     49     }
     50     Next[s] = head[h];
     51     head[h] = s;
     52     return 1;
     53 }
     54 
     55 int bfs() {
     56     init_lookup_table();
     57     int front = 1,rear = 2;
     58     while (front < rear) {
     59         State &s = st[front];
     60         if (memcmp(goal,s, sizeof(s)) == 0) {
     61             return front;
     62         }
     63         int z;
     64         for (z = 0;z < 9;z++) {
     65             if (!s[z])
     66                 break;
     67         }
     68         int x = z / 3,y = z % 3;
     69         for (int d = 0;d < 4;d++) {
     70             int newx = x + dx[d];
     71             int newy = y + dy[d];
     72             int newz = newx * 3  +newy;
     73             if (newx >= 0 && newx < 3 && newy >= 0 && newy < 3) {
     74                 State &t = st[rear];
     75                 memcpy(&t,&s, sizeof(s));
     76                 t[newz] = s[z];
     77                 t[z] = s[newz];
     78                 dis[rear] = dis[front] + 1;
     79                 if (try_to_insert(rear))
     80                     rear++;
     81             }
     82         }
     83         front++;
     84     }
     85     return 0;
     86 }
     87 
     88 
     89 int main() {
     90     int t;
     91     scanf("%d",&t);
     92     while (t--) {
     93         for (int i = 0; i < 9; i++) {
     94             scanf("%d", &st[1][i]);
     95         }
     96         for (int i = 0; i < 9; i++)
     97             scanf("%d", &goal[i]);
     98         int ans = bfs();
     99         if (ans > 0)
    100             printf("%d
    ", dis[ans]);
    101         else
    102             printf("-1
    ");
    103     }
    104     return 0;
    105 }
    Ackerman
  • 相关阅读:
    mybatis plus使用redis作为二级缓存
    netty无缝切换rabbitmq、activemq、rocketmq实现聊天室单聊、群聊功能
    netty使用EmbeddedChannel对channel的出入站进行单元测试
    记jdk1.8中hashmap的tableSizeFor方法
    Cannot find class: BaseResultMap
    windows下远程访问Redis,windows Redis绑定ip无效,Redis设置密码无效,Windows Redis 配置不生效,Windows Redis requirepass不生效,windows下远程访问redis的配置
    学习记录
    eclipse的注释
    转:聊聊同步、异步、阻塞与非阻塞
    点滴笔记(二):利用JS对象把值传到后台
  • 原文地址:https://www.cnblogs.com/-Ackerman/p/12191981.html
Copyright © 2011-2022 走看看