( ext{Description})
( ext{Solution})
先开始看到这题真的毫无头绪。
这有一个结论:
从起点到 ((x,y)),若有一种方案使得向左的步数最小,这种方案同时也是向右步数最小。反之一样。
证明:我们先选择向左步数最小的方案走。现在考虑将向左步数增加,发现每增加 (1) 都需要 (1) 次向右步数抵消。结论得证。
这样如果我们保证总左右步数最小,其实就是分别向左步数,向右步数最小。
所以我们令左右走为 (1) 步,上下走为 (0) 步。那么跑一个 ( ext{01 bfs}) 保证总步数最小即总左右步数最小,不能拓展到的点显然怎么调整都无法拓展到了。
这里讲一下 ( ext{01 bfs}) 吧:
适用于只有 (0,1) 两种边权的图的最短路,利用双端队列实现。如果边权为 (0) 就塞进队头,边权为 (1) 就塞进队尾。
证明一下它的正确性(即对于编号 (u),先取出来的最优):初始队列是满足这样的条件的。其实可以发现,队列前面一段由边权为 (0) 的边拓展而来的点一定步数相等(首先队列没有由 (0) 边拓展而来的点,若开始有了一个点令其为 (x),(x) 拓展出的 (1) 边放到队尾,拓展出的 (0) 边放到队首,权值是不变的。相当于队列前面一段由边权为 (0) 的边拓展而来的点被 (x) 这一大家子垄断了)。显然后面也是按步数排的。
( ext{Code})
#include <cstdio>
#define rep(i,_l,_r) for(register signed i=(_l),_end=(_r);i<=_end;++i)
#define fep(i,_l,_r) for(register signed i=(_l),_end=(_r);i>=_end;--i)
#define erep(i,u) for(signed i=head[u],v=to[i];i;i=nxt[i],v=to[i])
#define efep(i,u) for(signed i=Head[u],v=to[i];i;i=nxt[i],v=to[i])
#define print(x,y) write(x),putchar(y)
template <class T> inline T read(const T sample) {
T x=0; int f=1; char s;
while((s=getchar())>'9'||s<'0') if(s=='-') f=-1;
while(s>='0'&&s<='9') x=(x<<1)+(x<<3)+(s^48),s=getchar();
return x*f;
}
template <class T> inline void write(const T x) {
if(x<0) return (void) (putchar('-'),write(-x));
if(x>9) write(x/10);
putchar(x%10^48);
}
template <class T> inline T Max(const T x,const T y) {if(x>y) return x; return y;}
template <class T> inline T Min(const T x,const T y) {if(x<y) return x; return y;}
template <class T> inline T fab(const T x) {return x>0?x:-x;}
template <class T> inline T gcd(const T x,const T y) {return y?gcd(y,x%y):x;}
template <class T> inline T lcm(const T x,const T y) {return x/gcd(x,y)*y;}
#include <queue>
using namespace std;
const int maxn=2005;
int ans,n,m,sx,sy,Left,Right,dir[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
char s[maxn][maxn];
bool vis[maxn][maxn];
struct node {
int x,y,l,r;
};
deque <node> q;
void ZO_bfs() {
q.push_front((node){sx,sy,Left,Right});
while(!q.empty()) {
node t=q.front(); q.pop_front();
if(vis[t.x][t.y]||t.l<0||t.r<0) continue;
++ans;
vis[t.x][t.y]=1;
rep(i,0,3) {
int tx=t.x+dir[i][0],ty=t.y+dir[i][1];
if(tx<1||ty<1||tx>n||ty>m||s[tx][ty]=='*'||vis[tx][ty]) continue;
if(i==0||i==2) q.push_front((node){tx,ty,t.l,t.r});
else if(i==1) q.push_back((node){tx,ty,t.l,t.r-1});
else q.push_back((node){tx,ty,t.l-1,t.r});
}
}
}
int main() {
n=read(9),m=read(9),sx=read(9),sy=read(9),Left=read(9),Right=read(9);
rep(i,1,n) scanf("%s",s[i]+1);
ZO_bfs();
print(ans,'
');
return 0;
}