zoukankan      html  css  js  c++  java
  • bzoj5138 [Usaco2017 Dec]Push a Box

    题目描述:

    bz

    luogu

    题解:

    暴力可以记录$AB$位置转移,这个时候状态是$n^4$的,无法接受。

    考虑只记录$A$在$B$旁边时的状态,这个时候状态时$n^2$的。

    所以说转移有两种,一种是$A$推$B$一下,另一种是$A$绕到$B$另一侧。

    第一种转移显然$O(1)$,瓶颈在第二种。

    发现这对点满足点双,所以建出广义圆方树,判两个点是否同父亲或一个点是另一个点的爷爷。

    时间复杂度$O(n^2)$。

    代码:

    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N = 1550;
    template<typename T>
    inline void read(T&x)
    {
        T f = 1,c = 0;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
        x = f*c;
    }
    int n,m,Q,nam[N][N],tot,rtx,rty,rt,stx,sty,st,hed[N*N],cnt=1;
    char mp[N][N];
    bool check(int x,int y){return x&&y&&x<=n&&y<=m;}
    int dx[4]={-1,1,0,0},dy[4]={0,0,-1,1};
    struct EG
    {
        int to,nxt;
    }e[4*N*N];
    void ae(int f,int t)
    {
        e[++cnt].to = t;
        e[cnt].nxt = hed[f];
        hed[f] = cnt;
    }
    int dfn[N*N],low[N*N],tim,fa[N*N*2];
    int sta[N*N*2],tl;
    void tarjan(int u,int f)
    {
        dfn[u] = low[u] = ++tim;
        sta[++tl] = u;
        for(int j=hed[u];j;j=e[j].nxt)
        {
            int to = e[j].to;
            if(to==f)continue;
            if(!dfn[to])
            {
                tarjan(to,u);
                low[u] = min(low[u],low[to]);
                if(low[to]>=dfn[u])
                {
                    int now = ++tot;
                    fa[now] = u;
                    int c = -1;
                    while(c!=to)
                    {
                        c = sta[tl--];
                        fa[c] = now;
                    }
                }
            }else    low[u] = min(low[u],dfn[to]);
        }
    }
    bool ck(int u,int v)
    {
        if(fa[u]==fa[v])return 1;
        if(fa[fa[v]]==u)return 1;
        if(fa[fa[u]]==v)return 1;
        return 0;
    }
    bool dp[N][N][4];
    bool vis[N][N];
    struct Pair
    {
        int x,y;
        Pair(){}
        Pair(int x,int y):x(x),y(y){}
    };
    void bfs()
    {
        queue<Pair>q;
        q.push(Pair(rtx,rty));
        vis[rtx][rty] = 1;
        while(!q.empty())
        {
            Pair tp = q.front();q.pop();
            int x = tp.x,y = tp.y;
            for(int k=0;k<4;k++)
            {
                int xx = x+dx[k],yy = y+dy[k];
                if(!nam[xx][yy])continue;
                if(xx==stx&&yy==sty)dp[stx][sty][k]=1;
                else if(!vis[xx][yy])vis[xx][yy]=1,q.push(Pair(xx,yy));
            }
        }
    }
    struct Tri
    {
        int x,y,z;
        Tri(){}
        Tri(int x,int y,int z):x(x),y(y),z(z){}
    };
    void sol()
    {
        queue<Tri>q;
        for(int k=0;k<4;k++)if(dp[stx][sty][k])
            q.push(Tri(stx,sty,k));
        while(!q.empty())
        {
            Tri tp = q.front();
            q.pop();
            int x = tp.x,y = tp.y,k = tp.z;
            if(nam[x+dx[k]][y+dy[k]]&&!dp[x+dx[k]][y+dy[k]][k])dp[x+dx[k]][y+dy[k]][k]=1,q.push(Tri(x+dx[k],y+dy[k],k));
            for(int i=0;i<4;i++)if(nam[x-dx[i]][y-dy[i]]&&i!=k&&ck(nam[x-dx[k]][y-dy[k]],nam[x-dx[i]][y-dy[i]])&&!dp[x][y][i])
                dp[x][y][i]=1,q.push(Tri(x,y,i));
        }
    }
    bool cck(int x,int y){return dp[x][y][0]||dp[x][y][1]||dp[x][y][2]||dp[x][y][3]||(x==stx&&y==sty);}
    int main()
    {
    //    freopen("tt.in","r",stdin);
        read(n),read(m),read(Q);
        for(int i=1;i<=n;i++)
        {
            scanf("%s",mp[i]+1);
            for(int j=1;j<=m;j++)if(mp[i][j]!='#')
            {
                nam[i][j] = ++tot;
                if(mp[i][j]=='A')rt=tot,rtx=i,rty=j;
                if(mp[i][j]=='B')st=tot,stx=i,sty=j;
            }
        }
        for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)if(mp[i][j]!='#')
        {
            int u = nam[i][j];
            for(int x,y,k=0;k<4;k++)
            {
                x = i+dx[k],y = j+dy[k];
                if(!check(x,y)||mp[x][y]=='#')continue;
                ae(u,nam[x][y]);
            }
        }
        tarjan(rt,0);
        bfs();sol();
        for(int x,y,i=1;i<=Q;i++)
        {
            read(x),read(y);
            puts(cck(x,y)?"YES":"NO");
        }
        return 0;
    }
    View Code
  • 相关阅读:
    图片展示和上传需要注意的问题
    大数据技能学习
    C#100万条数据导入SQL SERVER数据库仅用4秒 (附源码)
    领导力
    .NetCore 三种生命周期注入方式
    Redis常见面试题
    .NET Core开发日志——Middleware
    编程的灵魂
    递推算法
    分治算法
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/10832055.html
Copyright © 2011-2022 走看看