zoukankan      html  css  js  c++  java
  • HDU-4531 吉哥系列故事——乾坤大挪移 模拟

    题意:给定一个九宫格,然后能够选择某行或者是某列滚动,每个小方格分为上下左右四个块,每个块可以涂上4种不同的颜色。问最少使用多少步能够使得所有相同颜色相互联通。

    分析:由于九宫格的所有的状态只有9!(362880)种,于是想起了先对每个格子进行标号,然后根据逆序对的数量进行一个递增进制数的hash处理,这样bfs搜索就能够去重了,接着只需要判断每个状态是否满足联通即可。这里的判定选择了先统计了不同颜色格子的数量然后dfs搜索,应该并查集也可以搞。滚动使用指针滚动即可,对于不能动的格子该格子所在行和列都不能够滚动。

    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    using namespace std;
    
    // 9! = 362880
    const int LIM = 362880;
    int fac[9]; // 递增进制数的权值 
    int tot[4]; // 四种颜色的个数 
    char vis[LIM]; // hash九宫格 
    char op[6]; // 滚动的操作的限制 
    char hav[50]; // 4*9个格子的标记 
    
    struct Block {
        char color[6];
        int id;
    }bk[3][3];
    
    struct Node {
        Block *ptr[3][3];
        int key;
        int ti;
        Node() {}
        Node(Block (*x)[3]) {
            ti = 0;
            for (int i = 0; i < 3; ++i) {
                for (int j = 0; j < 3; ++j) {
                    ptr[i][j] = &x[i][j]; 
                }
            }
            getkey();
        }
        void show() {
            for (int i = 0; i < 3; ++i) {
                for (int j = 0; j < 3; ++j) {
                    printf("%5d", ptr[i][j]->id);
                }
                puts("");
            }
            puts("");
        }
        void getkey() {
            int cnt;
            key = 0;
            for (int i = 0; i < 8; ++i) {
                cnt = 0;
                for (int j = i+1; j < 9; ++j) {
                    if (ptr[j/3][j%3]->id < ptr[i/3][i%3]->id) ++cnt;
                }
                key += cnt * fac[8-i];
            }
        }
        int dfs(int x, int y, int z) {
            if (hav[(x*3+y)*4+z]) return 0;
            hav[(x*3+y)*4+z] = 1;
            char ch = ptr[x][y]->color[z];
            int ret = 1;
            if (z == 0) {
                if (ptr[x][y]->color[2] == ch) ret += dfs(x, y, 2);
                if (ptr[x][y]->color[3] == ch) ret += dfs(x, y, 3);
                if (x > 0 && ptr[x-1][y]->color[1] == ch) ret += dfs(x-1, y, 1);
            } else if (z == 1) {
                if (ptr[x][y]->color[2] == ch) ret += dfs(x, y, 2);
                if (ptr[x][y]->color[3] == ch) ret += dfs(x, y, 3);
                if (x < 2 && ptr[x+1][y]->color[0] == ch) ret += dfs(x+1, y, 0);
            } else if (z == 2) {
                if (ptr[x][y]->color[0] == ch) ret += dfs(x, y, 0);
                if (ptr[x][y]->color[1] == ch) ret += dfs(x, y, 1);
                if (y > 0 && ptr[x][y-1]->color[3] == ch) ret += dfs(x, y-1, 3);
            } else {
                if (ptr[x][y]->color[0] == ch) ret += dfs(x, y, 0);
                if (ptr[x][y]->color[1] == ch) ret += dfs(x, y, 1);
                if (y < 2 && ptr[x][y+1]->color[2] == ch) ret += dfs(x, y+1, 2);
            }
            return ret;
        }
        bool judge() {
            memset(hav, 0, sizeof (hav));
            for (int i = 0; i < 3; ++i) {
                for (int j = 0; j < 3; ++j) {
                    for (int k = 0; k < 4; ++k) {
                        if (!hav[(i*3+j)*4+k]) {
                            int cnt = dfs(i, j, k);
                            switch(ptr[i][j]->color[k]) {
                                case 'R': if (cnt != tot[0]) return false; break;
                                case 'G': if (cnt != tot[1]) return false; break;
                                case 'B': if (cnt != tot[2]) return false; break;
                                default : if (cnt != tot[3]) return false;
                            }
                        }
                    }
                }
            }
            return true;
        }
    };
    
    void pre() {
        fac[1] = 1;
        for (int i = 2; i < 9; ++i) {
            fac[i] = fac[i-1] * i;
        }
    }
    
    void swapr(Block *x[], Block *y[], int dir) { // 横向的滚动
        if (dir == 0) { // 向左
            y[0] = x[1], y[1] = x[2], y[2] = x[0];
        } else { // 向右
            y[0] = x[2], y[1] = x[0], y[2] = x[1];
        }
    }
    
    void swapc(Block *x[], Block *y[], int dir) { // 纵向的滚动
        if (dir == 0) { // 向上 
            y[0] = x[3], y[3] = x[6], y[6] = x[0];
        } else { // 向下 
            y[0] = x[6], y[3] = x[0], y[6] = x[3];
        }
    }
    
    int bfs() {
        queue<Node>q;
        Node tmp = Node(bk);
        Node pos;
        memset(vis, 0, sizeof (vis));
        q.push(tmp); // 初始化是没有逆序对的
        vis[tmp.key] = 1;
        while (!q.empty()) {
            pos = q.front();
            q.pop();
            if (pos.judge()) {
                return pos.ti;
            }
            for (int i = 0; i < 6; ++i) {
                if (op[i]) continue;
                tmp = pos;
                if (i < 3) { // 横向的滚动 
                    for (int j = 0; j < 2; ++j) {
                        swapr(&pos.ptr[i][0], &tmp.ptr[i][0], j);
                        tmp.getkey();
                        tmp.ti = pos.ti + 1;
                        if (!vis[tmp.key]) {
                            vis[tmp.key] = 1;
                            q.push(tmp);
                        }
                    }
                } else { // 纵向的 
                    for (int j = 0; j < 2; ++j) {
                        swapc(&pos.ptr[0][i%3], &tmp.ptr[0][i%3], j);
                        tmp.getkey();
                        tmp.ti = pos.ti + 1;
                        if (!vis[tmp.key]) {
                            vis[tmp.key] = 1;
                            q.push(tmp);
                        }
                    }
                }
            }
        }
    }
    
    int main() {
        int T, ca = 0;
        pre();
        scanf("%d", &T);
        while (T--) {
            memset(op, 0, sizeof (op));
            memset(tot, 0, sizeof (tot));
            for (int i = 0; i < 3; ++i) {
                for (int j = 0; j < 3; ++j) {
                    scanf("%s", bk[i][j].color);
                    for (int k = 0; k < 4; ++k) {
                        switch(bk[i][j].color[k]) {
                            case 'R': ++tot[0]; break;
                            case 'G': ++tot[1]; break;
                            case 'B': ++tot[2]; break;
                            default : ++tot[3];
                        }
                    }
                    bk[i][j].id = i*3+j; // 0-8
                    if (bk[i][j].color[4] == '1') {
                        op[i] = op[3+j] = 1; // 两种操作无法进行
                    }
                }
            }
            printf("Case #%d: %d
    ", ++ca, bfs());
        }
        return 0;
    }
  • 相关阅读:
    RabbitMQ官方文档翻译之Simple(一)
    rabbitMq集成Spring后,消费者设置手动ack,并且在业务上控制是否ack
    RabbitMQ消息队列知识点归纳
    理解Java中HashMap的工作原理
    mybatis 主键回显
    quart任务调度框架实战
    springmvc常用注解标签详解
    Java程序员玩Linux学操作系统
    在网页中发起QQ临时对话的方法
    软件测试技术学习总结
  • 原文地址:https://www.cnblogs.com/Lyush/p/3416507.html
Copyright © 2011-2022 走看看