• CodeForces


    ( 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;
    }
    
  • 相关阅读:
    centOS学习part6:安装oracle 11g
    centOS学习part5:oracle 11g安装之环境准备
    centOS学习part4:安装配置vsftp
    centOS学习part3:远程工具VNC的安装与配置
    centOS学习part2:安装JDK及tomcat
    centOS学习part1:操作系统安装
    SSH开发实践part4:Spring整合Struts
    SSH开发实践part3:hibernate继承映射
    读《实战GUI自动化测试》之:第三步,如何提高测试结果分析的效率
    读《实战 GUI 产品的自动化测试》之:第二步,构建利于维护的自动化测试系统
  • 原文地址:https://www.cnblogs.com/AWhiteWall/p/14223471.html
Copyright © 2020-2023  润新知