1. 程式人生 > >[Codeforces Round #516][Codeforces 1063B/1064D. Labyrinth]

[Codeforces Round #516][Codeforces 1063B/1064D. Labyrinth]

通過 contest \n .com 起點 test 三維 amp open

題目鏈接: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); }
View Code

[Codeforces Round #516][Codeforces 1063B/1064D. Labyrinth]