• 【YBTOJ】【HDUOJ 3085】逃离噩梦


    题目大意:

    给定一张 (N imes M) 的地图,地图中有 (1) 个男孩,(1) 个女孩和 (2) 个鬼。

    字符 . 表示道路,字符 X 表示墙,字符 M 表示男孩的位置,字符 G 表示女孩的位置,字符 Z 表示鬼的位置。

    男孩每秒可以移动 (3) 个单位距离,女孩每秒可以移动 (1) 个单位距离,男孩和女孩只能朝上下左右四个方向移动。

    在第 (k) 秒后所有与鬼的曼哈顿距离不超过 (2 imes k) 的位置都会被鬼占领。

    每一秒鬼会先扩展,扩展完毕后男孩和女孩才可以移动。

    求在不进入鬼的占领区的前提下,男孩和女孩能否回合,若能回合,求出最短会和时间。

    (1<n,m<800)

    正文:

    双向 BFS 板子题。题目中的提示已经很足了。开两个队列分别搜男孩和女孩,就按着题目中给定的限制扩展即可。

    代码:

    const int N = 810;
    
    inline int READ() {
    	int x = 0, f = 1; char s = getchar();
    	while (s < '0' || s > '9') { if (s == '-') f = -f; s = getchar(); }
    	while (s >= '0' && s <= '9') { x = x * 10 + s - '0'; s = getchar(); }
    	return x * f;
    }
    
    struct point
    {
    	int x, y;
    }bs, gs;
    int n, m, gx1, gx2, gy1, gy2;;
    char a[N][N];
    int vis[N][N];
    int dx[4] = {0, 1, 0, -1},
        dy[4] = {1, 0, -1, 0};
    
    queue <point> q, t;
    
    bool ck(int x, int y, int k) {return x > 0 && x <= n && y > 0 && y <= m && a[x][y] != 'X' && a[x][y] != 'Z' && abs(x - gx1) + abs(y - gy1) > 2 * k && abs(x - gx2) + abs(y - gy2) > 2 * k;}
    
    void bfs()
    {
    	memset (vis, 0, sizeof vis);
    	while (!q.empty()) q.pop();
    	while (!t.empty()) t.pop();
    	q.push(bs), t.push(gs);
    	vis[bs.x][bs.y] = 1, vis[gs.x][gs.y] = 2;
    	for (int tim = 1; !q.empty() || !t.empty(); tim ++)
    	{
    		for (int j = 1; j <= 3; j++)
    		{
    			for (int k = q.size(); k--; )
    			{
    				point u = q.front();q.pop();
    				if (!ck(u.x, u.y, tim)) continue;
    				for (int i = 0; i < 4; i++)
    				{
    					int x = u.x + dx[i], y = u.y + dy[i];
    					if (!ck(x, y, tim)) continue;
    					if (vis[x][y] == 2)
    					{
    						printf ("%d
    ", tim);
    						return;
    					}
    					if (vis[x][y]) continue;
    					vis[x][y] = 1;
    					q.push((point){x, y});
    				}
    			}
    		}
    		for (int k = t.size(); k--; )
    		{
    			point u = t.front();t.pop();
    			if (!ck(u.x, u.y, tim)) continue;
    			for (int i = 0; i < 4; i++)
    			{
    				int x = u.x + dx[i], y = u.y + dy[i];
    				if (!ck(x, y, tim)) continue;
    				if (vis[x][y] == 1)
    				{
    					printf ("%d
    ", tim);
    					return;
    				}
    				if (vis[x][y]) continue;
    				vis[x][y] = 2;
    				t.push((point){x, y});
    			}
    		} 
    	} 
    	printf ("-1
    ");
    }
    
    int main()
    {
    	for(int t = READ(); t--; )
    	{
    		n = READ(), m = READ();
    		memset (a, 0, sizeof a);
    		gs = bs = (point){0, 0};
    		gx1 = gx2 = gy1 = gy2 = 0;
    		for (int i = 1; i <= n; i++)
    		{
    			scanf ("%s", a[i] + 1);
    			for (int j = 1; j <= m; j++)
    			{
    				if (a[i][j] == 'M') bs.x = i, bs.y = j;
    				if (a[i][j] == 'G') gs.x = i, gs.y = j;
    				if (a[i][j] == 'Z') 
    					if (!gx1) gx1 = i, gy1 = j;
    					else gx2 = i, gy2 = j;
    			}
    		}
    		bfs();
    	}
    	return 0;
    }
    
  • 相关阅读:
    澳门两日游之续一
    记澳门两日游0516
    [原创]北大ACM POJ 1050题解
    [原创]百度之星低频词过滤题解
    [原创]百度之星题解之重叠区间大小
    澳门两日游之续三
    澳门两日游之续二
    [原创]LZW网页判重的题解
    [原创]北大ACM POJ 1032题解
    创建产品列表控件时触发自定义DataUpated事件时,设置MultiView.ActiveViewIndex无效
  • 原文地址:https://www.cnblogs.com/GJY-JURUO/p/14658891.html
Copyright © 2020-2023  润新知