avatar
fireworks99
keep hungry keep foolish

Aizu 0121 Seven Puzzle

Description

给你一个4x2的方版,上面有0-7 八个数字,每次只能让编号0的方格跟他的上下左右的方格交换;所以也就是把方格0当做空格看待,每次只有空格周围的方格能够向空格处移动。 然后问从输入的方格样式变换到字典序最小的”01234567” 最少需要多少次.

Idea

https://cn.vjudge.net/problem/Aizu-0121

多组输入易超时的题:打表O(1)查询

打表:反向BFS,求出“01234567”到其他排列的最小步数

Code

#include <map>
#include <cmath>
#include <queue>
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

map<string, int> mp;
map<string, bool> vis;
int dir[] = {1, -1, 4, -4};

struct node
{
    string s;
    int zero, step;
};

void BFS()
{
    string ch = "01234567";
    mp[ch] = 0;
    vis[ch] = 1;
    node now, nxt;
    now.s = ch, now.zero = 0, now.step = 0;
    queue<node> q;
    q.push(now);
    while(q.size())
    {
        now = q.front();
        q.pop();


        for(int i = 0; i < 4; ++i)
        {
            int pos = now.zero + dir[i];
            if((pos < 0 || pos > 7) || (pos == 3 && now.zero == 4) || (pos == 4 && now.zero == 3))
                continue;
            string t = now.s;
            swap(t[now.zero], t[pos]);
            if(vis[t] == 0)
            {
                vis[t] = 1;
                nxt.s = t;
                nxt.zero = pos;
                nxt.step = now.step + 1;
                q.push(nxt);
                mp[t] = nxt.step;///make the table
            }
        }
    }
}

int main()
{
    BFS();
    char tem[20];
    while(~scanf("%c", &tem[0]))
    {
        for(int i = 1; i < 8; ++i)
            getchar(), tem[i] = getchar();
        getchar();
        tem[8] = '\0';//堵光标
        cout << mp[tem] << '\n';
    }
    return 0;
}
Site by Baole Zhao | Powered by Hexo | theme PreciousJoy