牛客寒假算法基础集训营6 迷宫

链接:https://ac.nowcoder.com/acm/contest/332/J
来源:牛客网

迷宫
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
你在一个 n 行 m 列的网格迷宫中,迷宫的每一格要么为空,要么有一个障碍。
你当前在第 r 行第 c 列(保证该格子为空)。每次移动你可以向上下左右任意一个方向移动一格,前提是不能走到障碍上,也不能超出迷宫的边界。
你向左移动的次数不能超过 x 次,向右不能超过 y 次。
问在这种情况下,对于每个格子,是否存在一种移动方案让你走到它。
输出有多少个格子存在移动方案让你走到它。
输入描述:

第一行两个正整数 n,m 。
第二行两个正整数 r,c ,保证 1≤r≤n,1≤c≤m 。
第三行两个整数 x,y ,保证 0≤x,y≤109

 。
接下来 n 行,每行一个长度为 m 的字符串,
第 i 行第 j 个字符表示迷宫第 i 行第 j 列的格子,
字符为`.` 表示格子为空,字符为`*` 表示格子上有一个障碍。

输出描述:

输出一个数,表示有多少个格子存在移动方案让你走到它。

示例1
输入

4 5
3 2
1 2
.....
.***.
...**
*....

输出

10

说明

将能走到的格子用+标记:

+++..
+***.
+++**
*+++.

示例2
输入
复制

4 4
2 2
0 1
....
..*.
....
....

输出
复制

7

说明

.++.
.+*.
.++.
.++.

备注:

对于全部数据, 1≤n,m≤1000

据说cf原题,是个好题,挺有技巧的。

好像数据有点水的说。普通搜索老老实实模拟也能过。

 

题解:

牛客寒假算法基础集训营6 迷宫

巧就巧在知道h和l还有b就可以知道l和r用了几次,而且b和l,b和r 成正比,所以b最小,l和r同时最小。

所以就是一个,左右为1,上下为0, 01bfs问题。

所以用双向队列。

所以bfs的时候记录b的最小值,并推一**意细节就好了。

#include <bits/stdc++.h>
using namespace std;
#define mod 1000000007
#define LL long long
#define pai acos(-1)
#define MAXN 100
int n,m,r,c,x,y;
char mp[1005][1005];
int vis[1005][1005];
int go[4][2]={0,1,0,-1,1,0,-1,0};
struct no{
    int h,l,step;
    no(int a,int b,int c){
        h=a;l=b;step=c;
    }
};

bool check(int h,int l){
	if(mp[h][l]=='*')return 0;
	if(h<0||l<0||h>n-1||l>m-1) return 0;
	return 1; 
}

void bfs(){
	for(int i=0;i<=1002;i++)
		for(int j=0;j<=1002;j++)
			vis[i][j]=INT_MAX;
    deque<no>q;
    q.push_front(no{r,c,0});
    vis[r][c]=0; 
    while(!q.empty()){
    	no node=q.front();
		q.pop_front();
		int a=node.l-c,b=node.step;
    	int l=(b-a)/2,r=(a+b)/2;
    	for(int i=2;i<=3;i++){
    		int th=node.h+go[i][0];
    		int tl=node.l+go[i][1];
    		if(check(th,tl)==0) continue;
    		if(b>=vis[th][tl]) continue;
    		vis[th][tl]=b;
    		q.push_front(no{th,tl,b});
		}
		int th=node.h,tl=node.l+1;
		if(check(th,tl)&&b+1<vis[th][tl]){
			if(r+1<=y){
				vis[th][tl]=b+1;
				q.push_back(no{th,tl,b+1});
			}	
		}
		th=node.h,tl=node.l-1;
		if(check(th,tl)&&b+1<vis[th][tl]){
			if(l+1<=x){
				vis[th][tl]=b+1;
				q.push_back(no{th,tl,b+1});
			}	
		}
	}
    
}

int main(){
    cin>>n>>m>>r>>c>>x>>y;
    r--;c--;
    for(int i=0;i<n;i++) cin>>mp[i];
    bfs();
    int re=0;
	for(int i=0;i<n;i++)
		for(int j=0;j<m;j++)
			if(vis[i][j]!=INT_MAX) re++;
	cout<<re;
    return 0;
}