[HDU 1067] Gap BFS+哈希

http://acm.hdu.edu.cn/showproblem.php?pid=1067

题意:每次将比空白格前面一个数字大一的数字移动到空白格,如果空白格前面数字的个位数是 7 或者空白格前面是空白格则不能移动到这里。

思路:手写hash,BFS。

#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>

using namespace std;

const int mod = 1000007;

struct node{
    int step;
    int zero[4][2];
    int loca[4][8];
    int mapn[4][8];
    friend bool operator == (node a, node b){
        for(int i = 0; i < 4; i++){
            for(int k = 1; k < 8; k ++)
            {
                if(a.mapn[i][k] != b.mapn[i][k])
                    return false;
            }
        }
        return true;
    }
};

node endmap;
long long Hash[mod];

void Swap(node &w, int i, int sx, int sy, int tx, int ty)
{
    w.mapn[sx][sy] = w.mapn[tx][ty];
    w.mapn[tx][ty] = 0;
    w.zero[i][0] = tx;
    w.zero[i][1] = ty;
    w.loca[w.mapn[sx][sy]/10-1][w.mapn[sx][sy]%10-1] = sx * 10 + sy;
}


bool HashMap(node w)
{
    long long resl = 0;
    for(int i = 0; i < 4; i++){
        for(int k = 0; k < 8; k++)
        {
            resl = (resl << 1) + (long long)w.mapn[i][k];
        }
    }
    int hs = resl % mod;
    while(Hash[hs] != resl && Hash[hs]){
        hs = (hs + 5) % mod;
    }
    if(Hash[hs] == 0){
        Hash[hs] = resl;
        return false;
    }
    return true;
}


int Bfs(node w)
{
    queue<node>que;
    que.push(w);
    HashMap(w);
    while(!que.empty()){
        node r = que.front();
        que.pop();
        if(r == endmap)
            return r.step;
        for(int i = 0; i < 4; i++){
            int mid = r.mapn[r.zero[i][0]][r.zero[i][1]-1];
            if(mid % 10 == 7 || mid % 10 == 0)
                continue;
            w = r;
            w.step++;
            mid = mid + 1;
            int loc = w.loca[mid/10-1][mid%10-1];
            Swap(w, i, r.zero[i][0], r.zero[i][1], loc/10, loc%10);
            if(!HashMap(w)){
                que.push(w);
            }
        }
    }
    return -1;
}

int main()
{
    int Test;
    cin>>Test;
    for(int i = 0; i < 4; i++){
        for(int k = 0; k < 7; k++)
        {
            endmap.mapn[i][k] = 10 * (i + 1) + k + 1;
        }
        endmap.mapn[i][7] = 0;
    }
    while(Test--)
    {
        node w;
        memset(Hash, 0, sizeof(Hash));
        for(int i = 0; i < 4; i++){
            for(int k = 1; k < 8; k++)
            {
                cin>>w.mapn[i][k];
                if(w.mapn[i][k] % 10 == 1){
                    w.zero[w.mapn[i][k]/10-1][0] = i;
                    w.zero[w.mapn[i][k]/10-1][1] = k;
                    w.mapn[w.mapn[i][k]/10-1][0] = w.mapn[i][k];
                    w.mapn[i][k] = 0;
                }
                else{
                    w.loca[w.mapn[i][k]/10-1][w.mapn[i][k]%10-1] = i*10 + k;
                }
            }
        }
        w.step = 0;
        cout<<Bfs(w)<<endl;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

achonor

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值