Codeforces Round #516 (Div. 2, by Moscow Team Olympiad) D. Labyrinth (貪心,雙端佇列)
阿新 • • 發佈:2018-12-15
Description:
給出一個n*m的迷宮,和一個初始位置(r0,c0), 從該初始位置出發每次只能上下左右四個方向走,且一共最多隻能向左走x步,向右走y步,且不能經過障礙('*'),問一共可以到達迷宮中的多少個位置。
Input:
m,n,r0,c0,x,y和迷宮
Output:
迷宮中可達的位置個數。
Analysis:
這一題首先看起來就是個搜尋問題,但是資料較大,直接dfs或是bfs都要超時。考慮貪心,儘量少的向左或者向右走的路徑必然是更優的,可以用一個雙端佇列,在bfs時,每次擴充套件都將上下方向走的下一個新的節點放入隊頭,而向左或者向右的節點放入隊尾,進行擴充套件,每次擴充套件都要標記vis[r][c]=1,這樣在這個過程中先擴充套件到的節點必然也是優於後擴充套件到的。所以可以直接在此剪枝,這樣,圖中每個點最多都只要訪問一次即可。
#include<iostream> #include<cstring> #include<algorithm> #include<map> #include<set> #include<queue> #include<sstream> #include<cmath> #include<iterator> #include<bitset> #include<stdio.h> #include<unordered_set> #include<ctime> #include<float.h> using namespace std; #define _for(i,a,b) for(int i=(a);i<(b);++i) #define _rep(i,a,b) for(int i=(a);i<=(b);++i) typedef long long LL; const int INF = 1 << 30; const int maxn = 2005; char pic[maxn][maxn]; int n, m,r0,c0,X,Y; bool vis[maxn][maxn]; struct Node { int r, c, x, y; Node(){} Node(int r,int c,int x,int y):r(r),c(c),x(x),y(y){} }; int dr[] = { -1,1,0,0 }, dc[]={0,0,-1,1}; bool OK(int r, int c) { return r >= 0 && r < n&&c >= 0 && c < m&&pic[r][c]=='.'; } int main() { //freopen("C:\\Users\\admin\\Desktop\\in.txt", "r", stdin); //freopen("C:\\Users\\admin\\Desktop\\out.txt", "w", stdout); scanf("%d%d%d%d%d%d", &n, &m,&r0,&c0,&X,&Y); for (int i = 0; i < n; ++i) { scanf("%s", pic[i]); } r0--; c0--; deque<Node> Q; Q.push_back({ r0,c0,X,Y }); int ans = 0; while (Q.size()) { Node now = Q.front(); Q.pop_front(); if (vis[now.r][now.c]) continue; vis[now.r][now.c] = 1; ans++; for (int dir = 0; dir < 4; ++dir) { int rr = now.r + dr[dir], cc = now.c + dc[dir]; int nx = (-(dir == 2)) + now.x, ny = (-(dir == 3)) + now.y; if (nx<0||ny<0)continue; if (OK(rr, cc)) { if(dir<=1) Q.push_front(Node{ rr, cc, nx, ny }); else Q.push_back(Node{ rr,cc,nx,ny }); } } } printf("%d\n", ans); return 0; }