• hdu4531 乾坤大挪移


    题意:中文题目(略)

    分析:其实就是一个暴力的bfs, 关键是模拟移动,判连通,以及状态的表示。

    每个格子移动过程中,内部四个小三角的相对顺序是不变的,也就是移动过程中,格子是作为一个整体在移动的,,小三角只是在判连通时才用到,所以状态的表示可以将每个格子作为一个整体,这样的话,总共就是9个格子,用0~8表示,这样是否很熟悉了? 可以用类似八数码的哈希方法,用康托展开将每一个状态hash到一个整数上,剩下的就是模拟了。

    很惭愧,单是敲这个代码就用了快俩个小时……

    hdu4531
    #include<iostream>
    #include<algorithm>
    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    #include<queue>
    #include<vector>
    
    using namespace std;
    
    const int N = 3;
    const int M = 362880 + 10;
    struct Grid
    {
        int a[4];
    }p[10];//保存初始时的9 个格子
    
    char str[10];
    int g[N][N];//记录移动过程中的地图,只记录对应格子的下标 0 ~ 8
    bool row[N], col[N];//记录该行或该列能否移动
    int a[N * N];//保存g对应的序列
    int cantor[9] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320};
    bool vis[M];
    
    int dir[4][3][3] = { {{-1,0,1}, {0,0,2}, {0,0,3}}, {{0,0,1}, {0,0,2}, {1,0,-1}}, {{0,0,-1}, {0,0,-2}, {0,-1,1}}, {{0,0,-3}, {0,0,-2}, {0,1,-1}}};
    //判连通是用到的, 预处理一下,方便找出每个小格子相邻的格子
    
    struct node
    {
        int state, step;
        node(){}
        node(int s, int st):state(s), step(st){}
    };
    
    void printMat()
    {
        for(int i = 0; i < N; ++i)
        {
            for(int j = 0; j < N; ++j)
                cout << g[i][j] << ' ' ;
            cout << endl;
        }
    }
    
    void gToA()//将g保存在数组a
    {
        int t = 0;
        for(int i = 0; i < N; ++i)
            for(int j = 0; j < N; ++j)
                a[t++] = g[i][j];
    }
    
    void aToG()//将数组a转化为矩阵
    {
        int t = 0;
        for(int i = 0; i < N; ++i)
            for(int j = 0; j < N; ++j)
                g[i][j] = a[t++];
    }
    
    int pack()//利用康托展开哈希
    {
        int ans = 0;
    
        gToA();
    
        for(int i = 0; i < 9; ++i)
        {
            int t = 0;
            for(int j = i + 1; j < 9; ++j)
                if(a[j] < a[i]) ++t;
            ans += t * cantor[8 - i];
        }
    
        return ans;
    }
    
    void unpack(int s)//将状态还原
    {
        char p[10] = {0};
    
        for(int i = 0; i < 9; ++i)
        {
            int t = s / cantor[8 - i], j;
            for(j = 0; j < 9; ++j)
                if(!p[j])
                {
                    if(t == 0) break;
                    --t;
                }
            a[i] = j;
            p[j] = 1;
            s %= cantor[8 - i];
        }
    
        aToG();
        return ;
    }
    
    bool mark[N][N][4];//标记每个格子上的小三角
    
    void dfs(int i, int j, int m, int color)
    {
        mark[i][j][m] = true;
        for(int k = 0; k < 3; ++k)
        {
            int xi = i + dir[m][k][0], yi = j + dir[m][k][1], t = m + dir[m][k][2];
            if( xi < 0 || xi >= N || yi < 0 || yi >= N || p[g[xi][yi]].a[t] != color) continue;
            if(mark[xi][yi][t]) continue;
            dfs(xi, yi, t, color);
        }
    }
    bool check()//判断是否连通
    {
        bool colorV[4] = {0};
        memset(mark, false, sizeof(mark));
        for(int i = 0; i < N; ++i)
            for(int j = 0; j < N; ++j)
            {
                for(int m = 0; m < 4; ++m)
                {
                    if(mark[i][j][m]) continue;
                    int color = p[g[i][j]].a[m];
                    if(colorV[color]) return false;//若同一个颜色存在俩个连通分量,则不符合
                    colorV[color] = true;
                    dfs(i, j, m, color);
                }
            }
        return true;
    }
    
    void shitRowL(int r)
    {
        int tmp = g[r][0];
        g[r][0] = g[r][1];
        g[r][1] = g[r][2];
        g[r][2] = tmp;
    }
    
    void shitRowR(int r)
    {
        int tmp = g[r][2];
        g[r][2] = g[r][1];
        g[r][1] = g[r][0];
        g[r][0] = tmp;
    }
    
    void shitColU(int c)
    {
        int tmp = g[0][c];
        g[0][c] = g[1][c];
        g[1][c] = g[2][c];
        g[2][c] = tmp;
    }
    
    void shitColD(int c)
    {
        int tmp = g[2][c];
        g[2][c] = g[1][c];
        g[1][c] = g[0][c];
        g[0][c] = tmp;
    }
    
    queue<node> Q;
    
    void addNode(int s, int st)
    {
        if(!vis[s]) {
            Q.push(node(s, st));
            vis[s] = true;
        }
    }
    
    int BFS(int s)
    {
        memset(vis,false,sizeof(vis));
        vis[s] = true;
        while(!Q.empty())
            Q.pop();
        Q.push(node(s, 0));
    
        while(!Q.empty())
        {
            node cur = Q.front();
            Q.pop();
            unpack(cur.state);
            //printMat();
            if(check())
                return cur.step;
            for(int i = 0; i < 3; ++i)
            {
                if(row[i])
                {
                    shitRowL(i);
                    int s = pack();
                    shitRowR(i);
                    addNode(s, cur.step + 1);
    
                    shitRowR(i);
                    s = pack();
                    shitRowL(i);
                    addNode(s, cur.step + 1);
                }
    
                if(col[i])
                {
    
                    shitColD(i);
                    s = pack();
                    shitColU(i);
                    addNode(s, cur.step + 1);
    
                    shitColU(i);
                    s = pack();
                    shitColD(i);
                    addNode(s, cur.step + 1);
                }
            }    
        }
        return -1;
    }
    int main()
    {
        int T, cas = 0;
        scanf("%d",&T);
        while(T--)
        {
            int t = 0;
    
            for(int i = 0; i < N; ++i)
            {
                row[i] = col[i] = true;
                for(int j = 0;j < N; ++j)
                {
                    scanf("%s",str);
                    for(int k = 0; k < 4; ++k)
                    {
                        if(str[k] == 'R')
                            p[t].a[k] = 0;
                        else if(str[k] == 'G')
                            p[t].a[k] = 1;
                        else if(str[k] == 'B')
                            p[t].a[k] = 2;
                        else p[t].a[k] = 3;
                    }
                    g[i][j] = t++;
                    if(str[4] == '1') 
                        col[j] = row[i] = false;
                }
            }
            printf("Case #%d: %d\n", ++cas, BFS(0));
        }
        return 0;
    }
  • 相关阅读:
    小球与盒子的故事
    2020.1.11 考试总结
    P4249 [WC2007]剪刀石头布
    P3825 [NOI2017]游戏
    BZOJ 2238 Mst
    P4240 毒瘤之神的考验
    生成函数(严重残缺)
    Min_25
    P3455 [POI2007]ZAP-Queries
    P3233 [HNOI2014]世界树
  • 原文地址:https://www.cnblogs.com/nanke/p/3003294.html
Copyright © 2020-2023  润新知