Disaster early warning (bfs + two points)

As we all know, Zhejiang Agriculture and Forestry is a river. Due to the special terrain of Zhejiang Agriculture and Forestry University, when you walk on the Agriculture and Forestry Road after rain, it is inevitable that you will step into a puddle with one foot. And Nong Nong doesn't like the feeling of stepping on a puddle. Please help to design a program to help Nong Nong determine whether he can go back to the bedroom without stepping into the puddle.

已知,浙江农林大学可以表示为一个 N * N 的矩阵。
对于每个位置有一个海拔数据 h[i][j],当水位高度大于 h[i][j] 的时候,
这个位置就会形成一个水坑。
农农现在的坐标是 (1, 1), 他的宿舍位于 (n, n).
农农只可以沿着上下左右四个方向走。
假如农农现在位于 (2, 2)那么在不考虑水位的情况下,他可以去的地方有 
  (1, 2)(2,1)(3, 2)(2, 3)

Input description:
N (indicates the size of the matrix)
next N lines are an N * N matrix h
Q (indicates the number of queries)
Next Q lines are a number per line, indicating the current water level X

1 <= N <= 1000
1 <= h[i][j] <= 100000
1 <= X <= 100000
1 <= Q <= 100000

Output description:
A total of Q lines, indicating whether Nong Nong can return to the bedroom without stepping into the puddle under the corresponding water level
, if Nong Nong can return to the bedroom, please output "Wuhu", otherwise please output
"Hmmm"
Example 1
Input
4
5 2 3 2
4 5 3 4
2 1 4 5
3 3 3 3
2
1
5
Output
Wuhu
Hmmm
Description
For the first query, no puddles are formed at any one position, so farmers can start from (1, 1 ) go to (4, 4)
for the second inquiry, the position where the height is less than 5 forms a puddle, which includes the destination (4, 4), so Nong Nong can
not go to (4, 4) without stepping on the puddle 4)

Link: https://ac.nowcoder.com/acm/contest/7872/M
Source : Niuke.com

Thought analysis:

O(n^2)When I did it at the time, my first reaction was dp, because I always thought that the time complexity was only when N was 1000, and I didn't O(n^2lgn)think about the direction. When building dp, I found that I couldn't satisfy no aftereffects anyway (because dp can only sweep from top to bottom, and can't consider the case of a certain path turning).
This is where my inexperience runs out.
If you think about it O(n^2lgn), you can think of the O(lgn) part to use bisection to find the maximum water level that this picture can reach the lower right corner. That is, it is necessary to detect whether it can go from the upper left corner to the lower right corner in O(n^2). This can be achieved with dfs or bfs.

code show as below:

bfs

#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;

int mp[1010][1010];
bool vis[1010][1010];
int dx[4] = {
    
    0,0,1,-1};
int dy[4] = {
    
    1,-1,0,0};
int n;


struct node{
    
    
	int x, y;
};

bool bfs(int h)
{
    
    
	if(mp[0][0] <= h) return false;
	memset(vis,0,sizeof(vis));
	vis[0][0] = 1;
	queue<node> q;
	q.push({
    
    0,0});
	while(!q.empty())
	{
    
    
		node t = q.front();
		q.pop();
		for(int k = 0;k < 4;k++)
		{
    
    
			int xx = t.x+dx[k];
			int yy = t.y+dy[k];
			if(xx >= 0 && xx < n && yy >= 0 && yy < n && !vis[xx][yy] && mp[xx][yy] >= h)
			{
    
    
				q.push({
    
    xx,yy});
				vis[xx][yy] = 1;
			}
		}
	}
	return vis[n-1][n-1];
}

int main()
{
    
    
	scanf("%d",&n);
	for(int i = 0;i < n;i++)
	{
    
    
		for(int j = 0;j < n;j++)
		{
    
    
			scanf("%d",&mp[i][j]);
		}
	}
	int l = 1, r = 1e5+1; //二分枚举[l,r)取右边界(相当于upper_bound),因此l-1为可走的最大水位 
	while(l < r)
	{
    
    
		int mid = (l+r)/2;
		if(bfs(mid)) l = mid+1; 
		else r = mid;
	}
	int q;
	scanf("%d",&q);
	while(q--)
	{
    
    
		int x;
		scanf("%d",&x);
		if(x <= l-1) printf("Wuhu\n");
		else printf("Hmmm\n");
	}
	return 0;
} 

dfs

#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;

int mp[1010][1010];
bool vis[1010][1010];
int dx[4] = {
    
    0,0,1,-1};
int dy[4] = {
    
    1,-1,0,0};
int n;
bool ok;

struct node{
    
    
	int x, y;
};

void dfs(int x, int y, int h)
{
    
    
	if(ok) return;
	if(mp[0][0] <= h) return;
	if(x == n-1 && y == n-1) ok = 1;
	for(int k = 0;k < 4;k++)
	{
    
    
		int xx = x+dx[k];
		int yy = y+dy[k];
		if(xx >= 0 && xx < n && yy >= 0 && yy < n && !vis[xx][yy] && mp[xx][yy] >= h)
		{
    
    
			vis[xx][yy] = 1;
			dfs(xx,yy,h);
		}
	}
} 

int main()
{
    
    
	scanf("%d",&n);
	for(int i = 0;i < n;i++)
	{
    
    
		for(int j = 0;j < n;j++)
		{
    
    
			scanf("%d",&mp[i][j]);
		}
	}
	int l = 1, r = 1e5+1; //二分枚举[l,r)取右边界(相当于upper_bound),因此l-1为可走的最大水位 
	while(l < r)
	{
    
    
		int mid = (l+r)/2;
		memset(vis,0,sizeof(vis));
		vis[0][0] = 1;
		ok = 0;
		dfs(0,0,mid);
		if(ok) l = mid+1; 
		else r = mid;
	}
	int q;
	scanf("%d",&q);
	while(q--)
	{
    
    
		int x;
		scanf("%d",&x);
		if(x <= l-1) printf("Wuhu\n");
		else printf("Hmmm\n");
	}
	return 0;
} 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325763089&siteId=291194637