zoukankan      html  css  js  c++  java
  • [NOIP2013]华容道

    1、题面

    小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次。于是,他想到用编程来完成华容道:给定一种局面,华容道是否根本就无法完成,如果能完成,最少需要多少时间。
    小 B 玩的华容道与经典的华容道游戏略有不同,游戏规则是这样的:

    1. 在一个 n*m 棋盘上有 n*m 个格子,其中有且只有一个格子是空白的,其余 n*m-1个格子上每个格子上有一个棋子,每个棋子的大小都是 1*1 的;
    2. 有些棋子是固定的,有些棋子则是可以移动的;
    3. 任何与空白的格子相邻(有公共的边)的格子上的棋子都可以移动到空白格子上。 游戏的目的是把某个指定位置可以活动的棋子移动到目标位置。

    给定一个棋盘,游戏可以玩 q 次,当然,每次棋盘上固定的格子是不会变的,但是棋盘上空白的格子的初始位置、指定的可移动的棋子的初始位置和目标位置却可能不同。第 i 次玩的时候,空白的格子在第 EX_i 行第 EY_i 列,指定的可移动棋子的初始位置为第 SX_i 行第 SY_i 列,目标位置为第 TX_i 行第 TY_i 列。
    假设小 B 每秒钟能进行一次移动棋子的操作,而其他操作的时间都可以忽略不计。请你告诉小 B 每一次游戏所需要的最少时间,或者告诉他不可能完成游戏。

    第一行有 3 个整数,每两个整数之间用一个空格隔开,依次表示 n、m 和 q;
    接下来的 n 行描述一个 n*m 的棋盘,每行有 m 个整数,每两个整数之间用一个空格隔开,每个整数描述棋盘上一个格子的状态,0 表示该格子上的棋子是固定的,1 表示该格子上的棋子可以移动或者该格子是空白的。
    接下来的 q 行,每行包含 6 个整数依次是 EX_i、EY_i、SX_i、SY_i、TX_i、TY_i,每两个整数之间用一个空格隔开,表示每次游戏空白格子的位置,指定棋子的初始位置和目标位置。

    输出有 q 行,每行包含 1 个整数,表示每次游戏所需要的最少时间,如果某次游戏无法完成目标则输出-1。

    2、总结

    暂时还不会写AC的啊,时隔数年再次利用这个题尝试了下NOIP中的BFS,略有点不顺畅,直接用四维标记数组来记录状态,但是会TLE20分,所以只有80分。求问怎么才AC呢。

    3、代码(80分)

    #include <cstdio>
    #include <cstring>
    #define MAXN 35
    
    const int vx[4] = {0, 0, 1, -1}, vy[4] = {1, -1, 0, 0};
    
    int n, m, t, a[MAXN][MAXN], vis[MAXN][MAXN][MAXN][MAXN];
    int ex, ey, sx, sy, tx, ty;
    
    struct Queue {
        int x, y, ox, oy, d;
    } q[MAXN * MAXN * MAXN * MAXN];
    
    int BFS() {
        int h = 1, t = 2;
        q[1] = (Queue) {ex, ey, sx, sy, 0};
        while (h != t) {
            for (int i = 0; i <= 3; i++) {
                int nx = q[h].x + vx[i], ny = q[h].y + vy[i];
                if (nx == q[h].ox && ny == q[h].oy) {
                    q[t].ox = q[h].x, q[t].oy = q[h].y;
                    if (q[t].ox == tx && q[t].oy == ty) return q[h].d + 1;
                }
                else q[t].ox = q[h].ox, q[t].oy = q[h].oy;
                if (!a[nx][ny] || vis[nx][ny][q[t].ox][q[t].oy]) continue;
                vis[nx][ny][q[t].ox][q[t].oy] = 1;
                q[t].x = nx, q[t].y = ny, q[t].d = q[h].d + 1;
                t++;
            }
            h++;
        }
        return -1;
    }
    
    int main() {
        freopen("1.in", "r", stdin);
        freopen("1.out", "w", stdout);
        scanf("%d %d %d", &n, &m, &t);
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= m; j++) scanf("%d", &a[i][j]);
        for (int i = 1; i <= t; i++) {
            memset(vis, 0, sizeof(vis));
            scanf("%d %d %d %d %d %d", &ex, &ey, &sx, &sy, &tx, &ty);
            vis[ex][ey][sx][sy] = 1;
            printf("%d
    ", sx == tx && sy == ty ? 0 :BFS());
        }
        return 0;
    }
  • 相关阅读:
    第36课 经典问题解析三
    第35课 函数对象分析
    67. Add Binary
    66. Plus One
    58. Length of Last Word
    53. Maximum Subarray
    38. Count and Say
    35. Search Insert Position
    28. Implement strStr()
    27. Remove Element
  • 原文地址:https://www.cnblogs.com/jinkun113/p/5860429.html
Copyright © 2011-2022 走看看