• 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;    
    }
  • 相关阅读:
    面向过程
    生成器
    迭代器
    装饰器
    函数及嵌套
    字符编码与文件操作
    linux_ssh
    LNMP
    BZOJ 3238: [Ahoi2013]差异
    BZOJ 3998: [TJOI2015]弦论
  • 原文地址:https://www.cnblogs.com/staginner/p/2659835.html
Copyright © 2020-2023  润新知