题目链接:http://codeforces.com/contest/1064/problem/D
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;
}