[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\n", 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\n", 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\n", 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;
}

 

posted @ 2018-10-13 17:13  zZhBr  阅读(149)  评论(0编辑  收藏  举报