zoukankan      html  css  js  c++  java
  • 立体推箱子2 Poj3323(可打表)

    题面

    达达发明了一种立体推箱子游戏。

    他发明的游戏里并没有那么多的规则和限制,在他的设定里游戏具有无限的平面空间,并且所有的区域都属于硬地。(关于立体推箱子游戏的各种概念和设定请参考172题)

    终点永远都位于坐标(0,0)处的情况下,请你求出从起点到终点所需的最少移动次数是多少。

    输入格式

    输入包含多组测试用例。

    每组测试数据在一行内,格式为 C x y,其中 C 为一个字母,x 和 y 是两个整数。

    这表示长方体覆盖住了平台上的格子(x, y),且其状态为 C。

    若 C 为字母 U,表明长方体是竖立的。

    若 C 为字母 V,表明长方体与 x 轴平行,且其覆盖的另一个格子为(x + 1, y)。

    若 C 为字母 H,表明长方体与 y 轴平行,且其覆盖的另一个格子为(x, y + 1)。

    输出格式

    对于每个测试用例,输出一个占一行的整数,表示所需的最少移动次数。

    3数据范围

    0≤x,y≤1000000000
    

    输入样例:

    U 0 0
    H 0 0
    V 1 0
    

    输出样例:

    0
    4
    1
    

    首先声明, 下表是从(0, 0)开始

    H 用 a(i, j), b(i, j + 1) 的 a 表示当前坐标

    V 用 a(i, j) b(i + 1, j) 的 a 表示当前坐标

    对于所有 i % 3 == 0, j % 3 == 0, 的(i, j) U 的状态 我们可以直接算(自己理解一下)

    并称 (i, j) 这个可以直接算的点为 [标状态] (i % 3 == 0, j % 3 == 0, x == 'U')

    所以我们就是先让题目给的状态, 转移到一个 [标状态] (i % 3 == 0, j % 3 == 0, x == 'U')

    任何一个(i, j) x状态 都处在一个九宫格,

    g0 g1 g2
    g3 g4 g5
    g6 g7 g8 (每个都是一个九宫格)
    

    我们假设 (i, j) 在九宫格 g4 中

    那我们的目的就是, 把(i, j) 转移到

    g3 g4 g6 g7 这四个九宫格内的 [标状态], 然后就翻滚到(0, 0)

    所以取这几个的 min就行了

    (题目给的都是非负数, 可以少考虑一些, 是负数稍微改改也能过)
    以上是基本思路, 实际上只需要转移到 g3 g4 g6 (毕竟是对称的)

    然后就先dfs求一边最小步数, 然后以后查询都是0(1)

    解释一下, 主要变量

    d[i][j][k][g] (i,j)是在九宫格内的坐标 ((0,0) ~ (2,2))
                   k 表状态 'U' 对应 0, 'V' 对应 1, 'H' 对应 2
                   g 表转移到哪个九宫格
                        0 表示 g4 到 g4 的 [标状态]
                        1      g4 到 g3 的 [      ]
                        2      g4    g6 的 [      ]
    

    怎么计算我就不说了吧

    想要打表也可以

    d[3][3][3][3] = 
    {{{2, 0, 4}, {4, 4, 5}, {5, 4, 5}}, {{5, 3, 5}, {5, 5, 6}, {3, 1, 5}}, {{6, 4, 6}, {6, 6, 7}, {6, 4, 6}}, 
    {{3, 3, 5}, {3, 1, 5}, {6, 5, 6}}, {{6, 6, 6}, {4, 2, 6}, {4, 2, 6}}, {{7, 6, 7}, {5, 3, 7}, {7, 5, 7}}, 
    {{4, 4, 6}, {4, 4, 6}, {7, 6, 7}}, {{6, 6, 7}, {5, 5, 7}, {5, 3, 7}}, {{7, 7, 8}, {6, 6, 8}, {7, 6, 8}}};
    
    #include <bits/stdc++.h>
    #define rep(i,a,b) for(int i=a;i<=b;++i)
    using namespace std;
    typedef long long ll;
    
    struct node { int x, y, z, t; }t, cur;
    
    int dx[3][4] = { {-2, 0, 1, 0}, {-1, 0, 2, 0}, {-1, 0, 1, 0} };
    int dy[3][4] = { {0, 1, 0, -2}, {0, 1, 0, -1}, {0, 2, 0, -1} };
    int dz[3][4] = { {1, 2, 1, 2}, {0, 1, 0, 1}, {2, 0, 2, 0} };
    int mp[9][9][3], d[3][3][3][4];
    
    void bfs(int x, int y, int z)
    {
        queue<node> q; q.push({ x, y, z, 0 });
        memset(mp, -1, sizeof mp); mp[x][y][z] = 0;
    
        while (!q.empty())
        {
            t = q.front(); q.pop(); cur.t = t.t + 1;
    
            rep(i, 0, 3)
            {
                cur.x = t.x + dx[t.z][i]; cur.y = t.y + dy[t.z][i]; cur.z = dz[t.z][i];
                if (cur.x < 0 || cur.x > 5 || cur.y < 0 || cur.y > 5) continue;
    
                if (mp[cur.x][cur.y][cur.z] == -1 || mp[cur.x][cur.y][cur.z] > cur.t)
                    mp[cur.x][cur.y][cur.z] = cur.t, q.push(cur);
            }
        }
    }
    
    void init()
    {
        rep (k, 0, 2)
            rep (i, 0, 2)
                rep (j, 0, 2)
                {
                    bfs(i + 3, j + 3, k);
                    d[i][j][k][0] = mp[3][0][0]; d[i][j][k][1] = mp[3][3][0];
                    d[i][j][k][2] = mp[0][0][0]; d[i][j][k][3] = mp[0][3][0];
                }
    }
    
    ll a, b;
    char op;
    
    ll calc(int c)
    {
        ll x = a / 3, y = b / 3; a %= 3, b %= 3;
        ll ans = d[a][b][c][1] + (x << 1) + (y << 1);
        if (y) ans = min(ans, d[a][b][c][0] + (x << 1) + (y - 1 << 1));
        if (x) ans = min(ans, d[a][b][c][2] + (x - 1 << 1) + (y - 1 << 1));
        return ans;
    }
    
    int main()
    {
        init();
        while (cin >> op >> a >> b)
        {
            int c = op == 'U' ? 0 : op == 'V' ? 1 : 2;
            if (a > b) swap(a, b), c = c == 0 ? 0 : c == 1 ? 2 : 1;
            cout << calc(c) << '
    ';
        }
        return 0;
    }
    
  • 相关阅读:
    线性表ADT实现
    基数排序
    二叉树之已知前序和中序遍历求后序遍历(POJ2255 &&HDU )
    acm头文件
    快排
    快读
    二分
    数据结构大师
    AC_2. 01背包问题
    AC_94. 递归实现排列型枚举
  • 原文地址:https://www.cnblogs.com/2aptx4869/p/12916439.html
Copyright © 2011-2022 走看看