牛客寒假算法基础集训营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原题,是个好题,挺有技巧的。
好像数据有点水的说。普通搜索老老实实模拟也能过。
题解:
巧就巧在知道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;
}