HDU 3278 Puzzle

HDU_3278

    尽管如果考虑有三种颜色的话状态数会很多,但如果一旦确定我们要将哪个颜色移到中间,其余的两个颜色就可以视作一种颜色,因此就可以先从终态开始bfs一遍,记录下结果,每次读一个图,就枚举三种颜色当作移到中间的颜色,然后O(1)查询步数即可。

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
#define HASH 1000007
#define MAXD 1000010
#define INF 0x3f3f3f3f
struct Point
{
    int st, d;
    Point(){}
    Point(int _st, int _d) : st(_st), d(_d){}
};
struct HashMap
{
    int head[HASH], size, next[MAXD], st[MAXD], d[MAXD];
    void init()
    {
        memset(head, -1, sizeof(head)), size = 0;
    }
    int find(int state)
    {
        int i, h = state % HASH;
        for(i = head[h]; i != -1; i = next[i])
            if(st[i] == state) return i;
        return -1;
    }
    void push(int state, int dis)
    {
        int i, h = state % HASH;
        st[size] = state, d[size] = dis;
        next[size] = head[h], head[h] = size ++;
    }
}hm;
char b[5][10];
int ANS, code[5][10];
void init()
{
    int i, j;
    for(i = 0; i < 4; i ++) scanf("%s", b[i]);
}
int encode()
{
    int i, j, ans = 0;
    for(i = 0; i < 4; i ++)
        for(j = 0; j < 6; j ++) ans = ans << 1 | code[i][j];
    return ans;
}
void decode(int st)
{
    int i, j;
    for(i = 3; i >= 0; i --)
        for(j = 5; j >= 0; j --) code[i][j] = st & 1, st >>= 1;
}
void shr(int r, int k)
{
    int i;
    if(k == 0) for(i = 0; i < 5; i ++) std::swap(code[r][i], code[r][i + 1]);
    else for(i = 5; i >= 1; i --) std::swap(code[r][i], code[r][i - 1]);
}
void shc(int c, int k)
{
    int i;
    if(k == 0) for(i = 0; i < 3; i ++) std::swap(code[i][c], code[i + 1][c]);
    else for(i = 3; i >= 1; i --) std::swap(code[i][c], code[i - 1][c]);
}
void prepare()
{
    int i, j, c;
    std::queue <Point> q;
    hm.init();
    memset(code, 0, sizeof(code));
    for(i = 1; i <= 2; i ++)
        for(j = 1; j <= 4; j ++) code[i][j] = 1;
    c = encode();
    q.push(Point(c, 0)), hm.push(c, 0);
    while(!q.empty())
    {
        Point p = q.front();
        q.pop();
        decode(p.st);
        for(i = 0; i < 4; i ++)
            for(j = 0; j < 2; j ++)
            {
                shr(i, j), c = encode();
                if(hm.find(c) == -1) q.push(Point(c, p.d + 1)), hm.push(c, p.d + 1);
                shr(i, j ^ 1);
            }
        for(i = 0; i < 6; i ++)
            for(j = 0; j < 2; j ++)
            {
                shc(i, j), c = encode();
                if(hm.find(c) == -1) q.push(Point(c, p.d + 1)), hm.push(c, p.d + 1);
                shc(i, j ^ 1);    
            }
    }
}
void deal(char ch)
{
    int i, j, c;
    for(i = 0; i < 4; i ++)
        for(j = 0; j < 6; j ++) code[i][j] = b[i][j] == ch;
    c = encode();
    i = hm.find(c);
    ANS = std::min(ANS, hm.d[i]);
}
void solve()
{
    int i, j;
    ANS = INF;
    deal('B'), deal('W'), deal('G');
    printf("%d\n", ANS);
}
int main()
{
    int t, tt;
    prepare();
    scanf("%d", &t);
    for(tt = 1; tt <= t; tt ++)
    {
        init();
        printf("Case %d: ", tt);
        solve();    
    }
    return 0;    
}
原文地址:https://www.cnblogs.com/staginner/p/2659835.html