标签:数据 include close space pen getchar 方向 can 分享图片
题目链接:1063B - Labyrinth/1064D - Labyrinth
题目大意:给定一个\(n\times m\)的图,有若干个点不能走,上下走无限制,向左和向右走的次数分别被限制为\(x\)和\(y\),给出起点并询问有多少个点能够到达。
题解:简单BFS,但是有一些坑点。
我们都知道BFS时,一个点被第一次访问的时候就是代表着到达此点走的步数最少的方案,但这并不代表着这就是向左向右走次数最少的方案。这就会导致有时候到达一个点时,向右走的次数已经被耗尽,无法继续访问该点右边的点,那么该点右边的点就不会被访问。但是有可能有另一种方案,虽然其总步数较长,但是并不会耗费太多向右走的次数,通过这种方案是可以访问到该点右边的点的,但由于到达该点时已经被访问过了,就不会进行下一次操作。因此需要进行些处理。
把\(vis\)数组改成三维的,第三维代表是从哪个方向访问到的此点,BFS时也同时记录是从哪个方向过来访问到的此点,并防止走回头路(即如果是从下方走到的这个点,就不能回头往下走)就好了。
hack数据附在了代码中
/* 13 8 8 1 4 10 ...*...* .*.*.*.* .*.*.*.* .*.*.*.* .*.*.*.* .*.*.*.* .*...*.* .*****.. .....*.* ****.*.* .....*.* .*****.* .......* ans=57 */ #include<bits/stdc++.h> using namespace std; #define N 2001 struct rua{int x,y,d,a,b;}; int n,m,r,c,A,B,f[N][N],ans; bool vis[N][N][5]; 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(); q.push({r,c,0,A,B}); for(int i=1;i<=4;i++)vis[r][c][i]=true; while(!q.empty()) { rua cur=q.front();q.pop(); int x=cur.x,y=cur.y,d=cur.d,a=cur.a,b=cur.b; if(x>1 && !vis[x-1][y][1] && f[x-1][y] && d!=2)q.push({x-1,y,1,a,b}),vis[x-1][y][1]=true; if(x<n && !vis[x+1][y][2] && f[x+1][y] && d!=1)q.push({x+1,y,2,a,b}),vis[x+1][y][2]=true; if(a && y>1 && !vis[x][y-1][3] && f[x][y-1] && d!=4)q.push({x,y-1,3,a-1,b}),vis[x][y-1][3]=true; if(b && y<m && !vis[x][y+1][4] && f[x][y+1] && d!=3)q.push({x,y+1,4,a,b-1}),vis[x][y+1][4]=true; } for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { bool x=0; for(int k=1;k<=4;k++)x|=vis[i][j][k]; ans+=x; } printf("%d\n",ans); }
[Codeforces Round #516][Codeforces 1063B/1064D. Labyrinth]
标签:数据 include close space pen getchar 方向 can 分享图片
原文地址:https://www.cnblogs.com/DeaphetS/p/9787962.html