zoukankan      html  css  js  c++  java
  • CCF201604-4 游戏

    试题编号: 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。

          这题就是一个bfs求最短路,不过这题特殊的是有的格子在任何时候都是安全的,有的格子在某些时间是安全的,所以用了一个mp数组存了每个格子的危险时间,若mp[i][j]为-1,-1则说明该格子在任何时候都是安全的,否则在该时间段是危险的。这题一开始我写的时候没用vis数组超时了,有很多状态都是重复搜索了,因为但是我觉得这题标记格子有没有被访问过并没有用,因为有的格子可能被访问过了但是在该时间没有其他的格子走,就会回到之前走过了的格子,后来看了题解才知道,这个标记数组应该开3维的,标记i,j格子t时刻有没有被访问即可,这样就可以避免重复搜索了,三维大小开305就可以了,因为在搜索过程里出现的最大时刻也就300,因为当地图是100*100时,过了100个单位时间后所有的格子都必然是安全状态的(因为危险时间的上限是100),然后过了100单位时间后,从1,1到100,100是需要200步。

    #include<bits/stdc++.h>
    using namespace std;
    #define pii pair<int,int>
    int n,m,t;
    pii mp[105][105];
    int vis[105][105][1000];
    int d[4][2]={
        -1,0,
        1,0,
        0,1,
        0,-1
    };
    struct sta
    {
        pii pos;
        int ti;
        sta(int xx,int yy,int tii)
        {
            pos.first=xx;
            pos.second=yy;
            ti=tii;
        }
    };
    int bfs()
    {
        memset(vis,0,sizeof(vis));
        queue<sta>q;
        while(!q.empty()) q.pop();
        q.push(sta(1,1,0));
        vis[1][1][0]=1;
        while(!q.empty())
        {
            sta now=q.front();
            q.pop();
            if(now.pos.first==n&&now.pos.second==m)
            {
                return now.ti;
            }
            int x=now.pos.first,y=now.pos.second,ti=now.ti,nx,ny;
            for(int i=0;i<4;i++)
            {
                nx=x+d[i][0];
                ny=y+d[i][1];
                if(nx>=1&&nx<=n&&ny>=1&&ny<=m&&!vis[nx][ny][ti+1]&&(mp[nx][ny].first==-1||(((ti+1)<mp[nx][ny].first)||((ti+1)>mp[nx][ny].second))))
                    q.push(sta(nx,ny,ti+1)),vis[nx][ny][ti+1]=1;;
            }
    
        }
    }
    int main()
    {
        for(int i=1;i<=100;i++)
            for(int j=1;j<=100;j++)
                mp[i][j].first=mp[i][j].first=-1;
        scanf("%d %d %d",&n,&m,&t);
        while(t--)
        {
            int x,y,a,b;
            scanf("%d %d %d %d",&x,&y,&a,&b);
            mp[x][y]=make_pair(a,b);
        }
        cout<<bfs()<<endl;
        return 0;
    }
    
  • 相关阅读:
    有点忙啊
    什么是协程
    HDU 1110 Equipment Box (判断一个大矩形里面能不能放小矩形)
    HDU 1155 Bungee Jumping(物理题,动能公式,弹性势能公式,重力势能公式)
    HDU 1210 Eddy's 洗牌问题(找规律,数学)
    HDU1214 圆桌会议(找规律,数学)
    HDU1215 七夕节(模拟 数学)
    HDU 1216 Assistance Required(暴力打表)
    HDU 1220 Cube(数学,找规律)
    HDU 1221 Rectangle and Circle(判断圆和矩形是不是相交)
  • 原文地址:https://www.cnblogs.com/eason9906/p/11754883.html
Copyright © 2011-2022 走看看