zoukankan      html  css  js  c++  java
  • CCF201604-4 游戏(100分)


    试题编号: 201604-4
    试题名称: 游戏
    时间限制: 1.0s
    内存限制: 256.0MB
    问题描述:
    问题描述
      小明在玩一个电脑游戏,游戏在一个n×m的方格图上进行,小明控制的角色开始的时候站在第一行第一列,目标是前往第n行第m列。
      方格图上有一些方格是始终安全的,有一些在一段时间是危险的,如果小明控制的角色到达一个方格的时候方格是危险的,则小明输掉了游戏,如果小明的角色到达了第n行第m列,则小明过关。第一行第一列和第n行第m列永远都是安全的。
      每个单位时间,小明的角色必须向上下左右四个方向相邻的方格中的一个移动一格。
      经过很多次尝试,小明掌握了方格图的安全和危险的规律:每一个方格出现危险的时间一定是连续的。并且,小明还掌握了每个方格在哪段时间是危险的。
      现在,小明想知道,自己最快经过几个时间单位可以达到第n行第m列过关。
    输入格式
      输入的第一行包含三个整数n, m, t,用一个空格分隔,表示方格图的行数n、列数m,以及方格图中有危险的方格数量。
      接下来t行,每行4个整数r, c, a, b,表示第r行第c列的方格在第a个时刻到第b个时刻之间是危险的,包括a和b。游戏开始时的时刻为0。输入数据保证r和c不同时为1,而且当r为n时c不为m。一个方格只有一段时间是危险的(或者说不会出现两行拥有相同的r和c)。
    输出格式
      输出一个整数,表示小明最快经过几个时间单位可以过关。输入数据保证小明一定可以过关。
    样例输入
    3 3 3
    2 1 1 1
    1 3 2 10
    2 2 2 10
    样例输出
    6
    样例说明
      第2行第1列时刻1是危险的,因此第一步必须走到第1行第2列。
      第二步可以走到第1行第1列,第三步走到第2行第1列,后面经过第3行第1列、第3行第2列到达第3行第3列。
    评测用例规模与约定
      前30%的评测用例满足:0 < n, m ≤ 10,0 ≤ t < 99。
      所有评测用例满足:0 < n, m ≤ 100,0 ≤ t < 9999,1 ≤ r ≤ n,1 ≤ c ≤ m,0 ≤ a ≤ b ≤ 100。


    问题链接:CCF201604试题

    问题描述(参见上文)。

    问题分析:这是一个求最短路径的问题,即求最优问题,通常用BFS(广度优先搜索)来实现。本题也用BFS来实现,比较难以考虑到的是,需要一个三维的标志来避免重复搜索。除了行列坐标外,还需要考虑时间因素,所以是三维的。因为一些格在某个时间范围是危险的,不可进入,但是这个时间范围之外,是可以随意进入的。所以有时候需要在一些地方踱步,等过了这段时间再前行,就不能简单地限制为进入过的格不能再进入。

    程序说明:把格的危险时间范围存储在数组visited[][][]中,使得程序逻辑变得更加简洁,同时也节省了存储。其他都是套路。

    提交后得100分的C++语言程序如下:

    /* CCF201604-4 游戏 */
    
    #include <iostream>
    #include <cstring>
    #include <queue>
    
    using namespace std;
    
    const int N = 100;
    
    const int DIRECTSIZE = 4;
    struct direct {
        int drow, dcol;
    } direct[DIRECTSIZE] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
    
    int visited[N+1][N+1][300+1];
    
    struct node {
        int row, col, level;
    };
    
    int bfs(int n, int m)
    {
        node start, front, v;
        start.row = 1;
        start.col = 1;
        start.level = 0;
    
        queue<node> q;
        q.push(start);
    
        while(!q.empty()) {
            front = q.front();
            q.pop();
    
            // 到达终点则结束
            if(front.row == n && front.col == m)
                return front.level;
    
            for(int i=0; i<DIRECTSIZE; i++) {
                // 移动一格
                v.row = front.row + direct[i].drow;
                v.col = front.col + direct[i].dcol;
                v.level = front.level + 1;
    
                // 行列越界则跳过
                if(v.row < 1 || v.row > n || v.col < 1 || v.col > m)
                    continue;
    
                // 已经访问过的点不再访问
                if(visited[v.row][v.col][v.level])
                    continue;
    
                // 向前搜索:标记v点为已经访问过,v点加入队列中
                visited[v.row][v.col][v.level] = 1;
                q.push(v);
            }
        }
    
        return 0;
    }
    
    int main()
    {
        int n, m, t, r, c, a, b;
    
        // 变量初始化
        memset(visited, 0, sizeof(visited));
    
        // 输入数据
        cin >> n >> m >> t;
        for(int i=1; i<=t; i++) {
            cin >> r >> c >> a >> b;
    
            // 设置方格危险时间,使之那些时间不可进入
            for(int j=a; j<=b; j++)
                visited[r][c][j] = 1;
        }
    
        // BFS搜索
        int ans = bfs(n, m);
    
        // 输出结果
        cout << ans << endl;
    
        return 0;
    }


  • 相关阅读:
    js截取字符串区分汉字字母代码
    List 去处自定义重复对象方法
    63. Unique Paths II
    62. Unique Paths
    388. Longest Absolute File Path
    41. First Missing Positive
    140. Word Break II
    139. Word Break
    239. Sliding Window Maximum
    5. Longest Palindromic Substring
  • 原文地址:https://www.cnblogs.com/tigerisland/p/7564164.html
Copyright © 2011-2022 走看看