其他分享
首页 > 其他分享> > IOI2009 Day2 B Mecho小熊

IOI2009 Day2 B Mecho小熊

作者:互联网

Mecho

Problem Page (Codeforces IOI Archive)

Description

Mecho the bear has found a little treasure – the bees' secret honeypot, which is full of honey! He was happily eating his newfound treasure until suddenly one bee saw him and sounded the bee alarm. He knows that at this very moment hordes of bees will emerge from their hives and start spreading around trying to catch him. He knows he has to leave the honeypot and go home quickly, but the honey is so sweet that Mecho doesn't want to leave too soon. Help Mecho determine the latest possible moment when he can leave.

Mecho's forest is represented by a square grid of \(N×N\) unit cells, whose sides are parallel to the north-south and east-west directions. Each cell is occupied by a tree, by a patch of grass, by a hive or by Mecho's home. Two cells are considered adjacent if one of them is immediately to the north, south, east or west of the other (but not on a diagonal). Mecho is a clumsy bear, so every time he makes a step, it has to be to an adjacent cell. Mecho can only walk on grass and cannot go through trees or hives, and he can make at most \(S\) steps per minute.

At the moment when the bee alarm is sounded, Mecho is in the grassy cell containing the honeypot, and the bees are in every cell containing a hive (there may be more than one hive in the forest). During each minute from this time onwards, the following events happen in the following order:

In other words, the bees spread as follows: When the bee alarm is sounded, the bees only occupy the cells where the hives are located. At the end of the first minute, they occupy all grassy cells adjacent to hives (and still the hives themselves). At the end of the second minute, they additionally occupy all grassy cells adjacent to grassy cells adjacent to hives, and so on. Given enough time, the bees will end up simultaneously occupying all grassy cells in the forest that are within their reach.

Neither Mecho nor the bees can go outside the forest. Also, note that according to the rules above, Mecho will always eat honey for an integer number of minutes. The bees catch Mecho if at any point in time Mecho finds himself in a cell occupied by bees.

Write a program that, given a map of the forest, determines the largest number of minutes that Mecho can continue eating honey at his initial location, while still being able to get to his home before any of the bees catch him.

Format

Input

Your program must read from file input the following data:

It is guaranteed that the map will contain exactly one letter M, exactly one letter D and at least one letter H. It is also guaranteed that there is a sequence of adjacent letters G that connects Mecho to his home, as well as a sequence of adjacent letters G that connects at least one hive to the honeypot (i.e., to Mecho's initial location). These sequences might be as short as length zero, in case Mecho's home or a hive is adjacent to Mecho's initial location. Also, note that the bees cannot pass through or fly over Mecho's home. To them, it is just like a tree.

Output

Your program must write to standard output a single line containing a single integer: the maximum possible number of minutes that Mecho can continue eating honey at his initial location, while still being able to get home safely.

If Mecho cannot possibly reach his home before the bees catch him, the number your program writes to standard output must be \(−1\) instead.

Samples

Input

7 3
TTTTTTT
TGGGGGT
TGGGGGT
MGGGGGD
TGGGGGT
TGGGGGT
THHHHHT

Output

1

Explanation

In the first example, after eating honey for one minute, Mecho can take the shortest path directly to the right (→→→→→→) and he will be home in another two minutes, safe from the bees.

Input

7 3
TTTTTTT
TGGGGGT
TGGGGGT
MGGGGGD
TGGGGGT
TGGGGGT
TGHHGGT

Output

2

Explanation

In the second example After eating honey for two minutes, Mecho can take steps →↑→→↑→ during the third minute, then steps →→→→→→ during the fourth minute and steps ↓→↓→ during the fifth minute.

Constraints

解析

暴力二分答案+搜索题。单调性易于看出,重点在于搜索验证。很暴力,没什么好说的。

但是,有很多坑点,我碰到了,希望各位不要碰到:

  1. while(!Q.empty() && Q.front().s<wait)
    

    必须在没有取出队头元素前判断时间是否越界。不然,取出后,因为这个队列对后面有影响,会导致一些区域应该被蜜蜂占领的却没被标记。

  2. 严格遵循题目描述:小熊先走,蜜蜂后走。

  3. 小熊的家 D 蜜蜂不可入。

  4. memset(vis, 0, sizeof(vis));
    
    vis[start.x][start.y]=1;
    

    这两句话的次序问题。

这样,这题就解决了。看上去这题很吓人,实际上算法也不高端。但是细节很多,码量巨大。详见代码。

代码

// C
/*
Input
7 3
GGGGGGG 
GTTGTTG
GTTGTTG
MTTGTTD
GTTGTTG
GGGGGGG
HHHHHHH
Output
2

Input
5 1
DGMGG
GGGGG
GGGGG
GGGGG
GHGHG
Output
2
*/
#include <bits/stdc++.h>
#pragma GCC optimize ("Ofast")
#define SIZE 805
#define all(x) x.begin(), x.end()
#define debug(x) cout<<#x<<":"<<x<<endl;
using namespace std;

int n, mxstep;
char a[SIZE][SIZE];
bool vis[SIZE][SIZE];
bool bee[SIZE][SIZE];
struct node
{
	int x, y;
	int s;
	bool operator ==(node b)
	{
		return x==b.x && y==b.y;
	}
};
vector<node> hive;
node start;
node endpo;

int dx[]={-1, 1, 0, 0};
int dy[]={0, 0, -1, 1};

bool bfs(int wait)
{
	queue<node> q;	// bear
	q.push(start);
	queue<node> Q;	// bee
	memset(vis, 0, sizeof(vis));
	memset(bee, 0, sizeof(bee));
	vis[start.x][start.y]=1;
	for(node t:hive)
	{
		bee[t.x][t.y]=1;
		Q.push(t);
	}
	// 吃蜜时间蜜蜂围攻 
	while(!Q.empty() && Q.front().s<wait)
	{
		node w=Q.front(); Q.pop();
		int i=w.x, j=w.y;
		for(int k=0; k<4; k++)
		{
			int ni=i+dx[k];
			int nj=j+dy[k];
			// 不越界 
			if(ni<0 || ni>=n || nj<0 || nj>=n)
				continue;
			// 不走回头路 
			if(bee[ni][nj])
				continue;
			// 不入禁区 
			if(a[ni][nj]=='D' || a[ni][nj]=='T')
				continue;
			bee[ni][nj]=1;
			Q.push({ni, nj, w.s+1});
		}
	}
	// 原始位置已被攻占 
	if(bee[start.x][start.y])
		return 0;
	int steps=1;	// 行走的次数 
	while(!q.empty())
	{
		// 小熊先走 
		while(!q.empty() && q.front().s<steps*mxstep)
		{
			node w=q.front(); q.pop();
			int i=w.x, j=w.y;
			if(w==endpo) return 1;
			if(bee[i][j]) continue;
			for(int k=0; k<4; k++)
			{
				int ni=i+dx[k];
				int nj=j+dy[k];
				// 不越界
				if(ni<0 || ni>=n || nj<0 || nj>=n)
					continue;
				// 不被蜜蜂蛰 
				if(bee[ni][nj])
					continue;
				// 不走回头路 
				if(vis[ni][nj])
					continue;
				// 不入禁区 
				if(a[ni][nj]=='T')
					continue;
				vis[ni][nj]=1;
				q.push({ni, nj, w.s+1});
			}
		}
		// 蜜蜂后走
		while(!Q.empty() && Q.front().s<wait+steps)
		{
			node w=Q.front(); Q.pop();
			int i=w.x, j=w.y;
			for(int k=0; k<4; k++)
			{
				int ni=i+dx[k];
				int nj=j+dy[k];
				// 不越界
				if(ni<0 || ni>=n || nj<0 || nj>=n)
					continue;
				// 不走回头路 
				if(bee[ni][nj])
					continue;
				// 不入禁区 
				if(a[ni][nj]=='D' || a[ni][nj]=='T')
					continue;
				bee[ni][nj]=1;
				Q.push({ni, nj, w.s+1});
			}
		}
		steps++;
	}
	return 0;
}

signed main()
{
	cin>>n>>mxstep;
	int si, sj;
	for(int i=0; i<n; i++)
		for(int j=0; j<n; j++)
		{
			cin>>a[i][j];
			if(a[i][j]=='H')
				hive.push_back({i, j, 0});
			if(a[i][j]=='M')
				start={i, j, 0};
			if(a[i][j]=='D')
				endpo={i, j, 0};
		}
	int l=0, r=n*n;
	int ans=-1;
	while(l<=r)
	{
		int m=(l+r)>>1;
		if(bfs(m))
		{
			ans=m;
			l=m+1;
		}
		else
			r=m-1;
	}
	cout<<ans;

    return 0;
}

标签:IOI2009,nj,continue,ni,Day2,bee,bees,Mecho
来源: https://www.cnblogs.com/jerrywang2009/p/16546633.html