题目链接:1063B - Labyrinth/1064D - Labyrinth
题目大意:给定一个\(n\times m\)的图,有若干个点不能走,上下走无限制,向左和向右走的次数分别被限制为\(x\)和\(y\),给出起点并询问有多少个点能够到达。
题解:此题坑多...本弱写裸BFS,WA了一百次_(:з」∠)_
考虑从点\(A\)到点\(B\)需要向左或者向右走的次数,可以发现若设向左走的次数为\(l\),向右走的次数为\(r\),则\(r-l\)是个定值,因此转换成最短路问题用最短路跑一遍就好了。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#include<bits/stdc++.h> using namespace std; #define N 2001 #define INF 1000000007 int n,m,r,c,A,B,f[N][N],ans; struct rua{int x,y;}; struct res { int a,b; res operator +(const res &t)const{return {a+t.a,b+t.b};} bool operator <(const res &t)const{return a!=t.a?a<t.a:b<t.b;} bool operator <=(const res &t)const{return a<=t.a && b<=t.b;} }dis[N][N]; bool vis[N][N]; queue<rua>q; int get() { char ch=getchar(); while(ch!='.' && ch!='*') ch=getchar(); return ch=='.'; } int main() { scanf("%d%d%d%d%d%d",&n,&m,&r,&c,&A,&B); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) f[i][j]=get(),dis[i][j]={INF,INF}; dis[r][c]={0,0}; q.push({r,c}),vis[r][c]=true; while(!q.empty()) { rua cur=q.front();q.pop(); int x=cur.x,y=cur.y; vis[x][y]=false; if(x>1 && f[x-1][y] && dis[x][y]<dis[x-1][y]) {dis[x-1][y]=dis[x][y];if(!vis[x-1][y])q.push({x-1,y}),vis[x-1][y]=true;} if(x<n && f[x+1][y] && dis[x][y]<dis[x+1][y]) {dis[x+1][y]=dis[x][y];if(!vis[x+1][y])q.push({x+1,y}),vis[x+1][y]=true;} if(y>1 && f[x][y-1] && dis[x][y]+(res){1,0}<dis[x][y-1]) {dis[x][y-1]=dis[x][y]+(res){1,0};if(!vis[x][y-1])q.push({x,y-1}),vis[x][y-1]=true;} if(y<m && f[x][y+1] && dis[x][y]+(res){0,1}<dis[x][y+1]) {dis[x][y+1]=dis[x][y]+(res){0,1};if(!vis[x][y+1])q.push({x,y+1}),vis[x][y+1]=true;} } for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(dis[i][j]<=res{A,B}) ans++; return printf("%d\n",ans),0; }