zoukankan      html  css  js  c++  java
  • [Luogu1379]八数码难题

    题目描述

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

    输入输出格式

    输入格式:

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

    输出格式:

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

    输入输出样例

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




    普通搜索7000ms
    #include <cstdio>
    #include <iostream>
    #include <queue>
    #include <map>
    using namespace std;
    #define reg register
    #define ll long long
    ll St, Ed;
    map<ll, int> vis;
    struct date {
        ll hsh;
        int stp;
    };
    const int dx[] = {0, 1, -1, 0, 0}, dy[] = {0, 0, 0, 1, -1};
    int main()
    {
        scanf("%lld", &St);
        Ed = 123804765;
        queue <date> q;
        q.push((date){St, 0});
        while(!q.empty())
        {
            ll hsh = q.front().hsh;
            int tp = q.front().stp;
            q.pop();
            if (hsh == Ed) {
                printf("%d
    ", tp);
                return 0;
            }
            int a[4][4];
            int tmp = hsh;
            for (reg int i = 3 ; i >= 1 ; i --)
                for (reg int j = 3 ; j >= 1 ; j --)
                    a[i][j] = tmp % 10, tmp /= 10;
            int x = 0, y = 0;
            for (reg int i = 1 ; i <= 3 ; i ++) 
                for (reg int j = 1 ; j <= 3 ; j ++)
                    if (!a[i][j]) {x = i, y = j;break;}
            for (reg int i = 1 ; i <= 4 ; i ++)
            {
                int tx = x + dx[i], ty = y + dy[i];
                if (tx <= 0 or tx > 3 or ty <= 0 or ty > 3) continue;
                swap(a[x][y], a[tx][ty]);
                int nhsh = 0;
                for (reg int i = 1 ; i <= 3 ; i ++)
                    for (reg int j = 1 ; j <= 3 ; j ++)
                        nhsh = nhsh * 10 + a[i][j];
                if (!vis[nhsh]) vis[nhsh] = 1, q.push((date){nhsh, tp + 1});
                swap(a[x][y], a[tx][ty]);
            }
        }
        return 0;
    }

    双向广搜242ms

    #include <cstdio>
    #include <iostream>
    #include <queue>
    #include <map>
    using namespace std;
    #define reg register
    #define ll long long
    ll St, Ed;
    map<ll, int> vis1, vis2;
    struct date {
        ll hsh;
        int stp;
    };
    const int dx[] = {0, 1, -1, 0, 0}, dy[] = {0, 0, 0, 1, -1};
    int main()
    {
        scanf("%lld", &St);
        Ed = 123804765;
        queue <date> q1, q2;
        q1.push((date){St, 0});
        q2.push((date){Ed, 0});
        vis1[St] = 0, vis2[Ed] = 0;
        if (St == Ed) return puts("0"), 0;
        while(!q1.empty() and !q2.empty())
        {
            ll hsh = q1.front().hsh;
            int tp = q1.front().stp;
            q1.pop();
            if (vis2[hsh]) {
                printf("%d
    ", tp + vis2[hsh]);
                return 0;
            }
            int a[4][4];
            int tmp = hsh;
            for (reg int i = 3 ; i >= 1 ; i --)
                for (reg int j = 3 ; j >= 1 ; j --)
                    a[i][j] = tmp % 10, tmp /= 10;
            int x = 0, y = 0;
            for (reg int i = 1 ; i <= 3 ; i ++) 
                for (reg int j = 1 ; j <= 3 ; j ++)
                    if (!a[i][j]) {x = i, y = j;break;}
            for (reg int i = 1 ; i <= 4 ; i ++)
            {
                int tx = x + dx[i], ty = y + dy[i];
                if (tx <= 0 or tx > 3 or ty <= 0 or ty > 3) continue;
                swap(a[x][y], a[tx][ty]);
                int nhsh = 0;
                for (reg int i = 1 ; i <= 3 ; i ++)
                    for (reg int j = 1 ; j <= 3 ; j ++)
                        nhsh = nhsh * 10 + a[i][j];
                if (!vis1[nhsh]) vis1[nhsh] = tp + 1, q1.push((date){nhsh, tp + 1});
                swap(a[x][y], a[tx][ty]);
            }
            hsh = q2.front().hsh;
            tp = q2.front().stp;
            q2.pop();
            if (vis1[hsh]) {
                printf("%d
    ", tp + vis1[hsh]);
                return 0;
            }
            tmp = hsh;
            for (reg int i = 3 ; i >= 1 ; i --)
                for (reg int j = 3 ; j >= 1 ; j --)
                    a[i][j] = tmp % 10, tmp /= 10;
            x = 0, y = 0;
            for (reg int i = 1 ; i <= 3 ; i ++) 
                for (reg int j = 1 ; j <= 3 ; j ++)
                    if (!a[i][j]) {x = i, y = j;break;}
            for (reg int i = 1 ; i <= 4 ; i ++)
            {
                int tx = x + dx[i], ty = y + dy[i];
                if (tx <= 0 or tx > 3 or ty <= 0 or ty > 3) continue;
                swap(a[x][y], a[tx][ty]);
                int nhsh = 0;
                for (reg int i = 1 ; i <= 3 ; i ++)
                    for (reg int j = 1 ; j <= 3 ; j ++)
                        nhsh = nhsh * 10 + a[i][j];
                if (!vis2[nhsh]) vis2[nhsh] = tp + 1, q2.push((date){nhsh, tp + 1});
                swap(a[x][y], a[tx][ty]);
            }        
        }
        return 0;
    }
  • 相关阅读:
    Yield Usage Understanding
    Deadclock on calling async methond
    How to generate file name according to datetime in bat command
    Run Unit API Testing Which Was Distributed To Multiple Test Agents
    druid的关键参数+数据库连接池运行原理
    修改idea打开新窗口的默认配置
    spring boot -thymeleaf-url
    @pathvariable和@RequestParam的区别
    spring boot -thymeleaf-域对象操作
    spring boot -thymeleaf-遍历list和map
  • 原文地址:https://www.cnblogs.com/BriMon/p/9783490.html
Copyright © 2011-2022 走看看