zoukankan      html  css  js  c++  java
  • 【USACO17DEC】Push a Box

    题面

    https://www.luogu.org/problem/P4082

    题解

    一道梵高级别的水题。但是因为是自己想出来的比较自豪,所以就写了。

    $F[x][y][s]$代表石头在$(x,y)$,人在$(x+dx[s],y+dy[s])$,转移有两种,一种是推一步,一种是换个方向。

    要判断“换个方向”时,是否可以走到那里,所以把点双求出来,把石头就看做割点,这里不需要建圆方树判断,因为如果它们不在一个点双里,说明只有唯一一条路(走石头),并且被堵上了,所以不能走过去,如果它们在一个点双里,说明可以到达。

    判断两点是不是在一个点双里,我想了一下,发现没有特别好的方法,题解也写的暴力,那就暴力吧。

    #include<stack>
    #include<queue>
    #include<vector>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define ri register int
    #define N 1550
    using namespace std;
    
    int n,m,q,vis[N][N],vis2[N][N][4],id[N][N];
    int dfn[N*N],low[N*N],cnt,bccnt;
    vector<int> bel[N*N];
    char g[N][N];
    stack<int> s;
    const int dx[]={1,-1,0,0};
    const int dy[]={0,0,1,-1};
    
    struct graph {
      vector<int> to[N*N];
      void add_edge(int u,int v) {to[u].push_back(v);}
      void tarjan(int x) {
        dfn[x]=low[x]=++cnt;
        s.push(x);
        for (ri i=0;i<to[x].size();i++) {
          int y=to[x][i];
          if (dfn[y]) {
            low[x]=min(low[x],dfn[y]);
          }
          else {
            tarjan(y);
            low[x]=min(low[x],low[y]);
            if (low[y]>=dfn[x]) {
              ++bccnt;
              while (1) {
                int t=s.top(); s.pop();
                bel[t].push_back(bccnt);
                if (t==y) break;
              }
              bel[x].push_back(bccnt);
            }
          }
        }
      }
    } G;
    
    struct node{int x,y;};
    struct node2{int x,y,s;};
    
    bool check(int ax,int ay,int bx,int by) {
      int a=id[ax][ay],b=id[bx][by];
      for (ri i=0;i<bel[a].size();i++)
        for (ri j=0;j<bel[b].size();j++) if (bel[a][i]==bel[b][j]) return 1;
      return 0;
    }
    
    void bfs2(int sx,int sy,int opt) {
      queue<node2> q;
      q.push((node2){sx,sy,opt}); vis2[sx][sy][opt]=1;
      while (!q.empty()) {
        int x=q.front().x,y=q.front().y,s=q.front().s;
        q.pop();
        for (ri i=0;i<4;i++) {
          if (i==s) continue;
          int nx=x+dx[i],ny=y+dy[i];
          if (!id[nx][ny] || vis2[x][y][i]) continue;
          if (check(nx,ny,x+dx[s],y+dy[s])) vis2[x][y][i]=1,q.push((node2){x,y,i});
        }
        int nx=x+dx[s^1],ny=y+dy[s^1];
        if (!id[nx][ny] || vis2[nx][ny][s]) continue;
        vis2[nx][ny][s]=1,q.push((node2){nx,ny,s});
      }
    }
    
    void bfs(int ax,int ay,int bx,int by) {
      queue<node> q;
      q.push((node){ax,ay}); vis[ax][ay]=1;
      while (!q.empty()) {
        int x=q.front().x,y=q.front().y;
        q.pop();
        for (ri i=0;i<4;i++) {
          int nx=x+dx[i],ny=y+dy[i];
          if (vis[nx][ny] || !id[nx][ny]) continue;
          vis[nx][ny]=1; q.push((node){nx,ny});
          if (nx==bx && ny==by) { bfs2(bx,by,i^1); return; }
        }
      }
    }
    
    int main(){
      scanf("%d %d %d",&n,&m,&q);
      memset(g,'#',sizeof(g));
      for (ri i=1;i<=n;i++) scanf("%s",g[i]+1),g[i][m+1]='#';
    
      int cc=0;
      for (ri i=1;i<=n;i++)
        for (ri j=1;j<=m;j++) if (g[i][j]!='#') id[i][j]=++cc;
    
      for (ri i=1;i<=n;i++) 
        for (ri j=1;j<=m;j++) if (id[i][j]) {
          for (ri k=0;k<4;k++) {
            int nx=i+dx[k],ny=j+dy[k];
            if (id[nx][ny]) G.add_edge(id[i][j],id[nx][ny]);
          }
        }
    
      for (ri i=1;i<=n;i++) 
        for (ri j=1;j<=m;j++) if (id[i][j] && !dfn[id[i][j]]) G.tarjan(id[i][j]);
    
      int ax,ay,bx,by;
      for (ri i=1;i<=n;i++) 
        for (ri j=1;j<=m;j++) if (g[i][j]=='A') ax=i,ay=j;
      for (ri i=1;i<=n;i++)
        for (ri j=1;j<=m;j++) if (g[i][j]=='B') bx=i,by=j;
      
      bfs(ax,ay,bx,by);
    
      int a,b;
      for (ri i=1;i<=q;i++) {
        scanf("%d %d",&a,&b);
        bool ans=(a==bx && b==by);
        for (ri j=0;j<4;j++) ans|=vis2[a][b][j];
        if (ans) puts("YES"); else puts("NO");
      }
      return 0;
    }
  • 相关阅读:
    ACM第六周竞赛题目——A LightOJ 1317
    数学概念——J
    数学概念——I
    数学概念——D 期望
    数学概念——A 几何概型
    数学概念——E 期望(经典问题)
    数学概念——F 概率(经典问题)birthday paradox
    数学概念——H 最美素数
    数学概念——G 最大公约数
    UVa1328
  • 原文地址:https://www.cnblogs.com/shxnb666/p/11420651.html
Copyright © 2011-2022 走看看