[关闭]
@ysner 2018-09-26T14:51:20.000000Z 字数 2724 阅读 1857

[USACO17DEC]Push a Box

图论


题面

戳我

解析

挺不错的一道图论码量题。
可以借此回顾一下华容道。

思路和华容道差不多。
照洛谷数据规模看,暴搜可能有的分数。。。

表示箱子在点时,人能否到达方向(即,表示上下左右)。
那么我们可以先从人出发一遍,预处理出未推箱子时的
注意箱子所在点是可以多次更新的。

然后开始推箱子,每次有两种决策:

决策可不可行肯定要预处理出来,毕竟级别的。
显然如果能换方向,就说明换方向的前后两点在同一点双联通分量中。
这玩意儿从人的出发点跑一遍就能预处理出来。
推一格这个操作可以直接转移。

注意边界都要赋为。(尤其是每行末尾)
细节挺多,蒟蒻调了两个多小时。。。

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstdlib>
  4. #include<cstring>
  5. #include<cmath>
  6. #include<algorithm>
  7. #include<queue>
  8. #include<vector>
  9. #define ll long long
  10. #define re register
  11. #define il inline
  12. #define pb(a) push_back(a)
  13. #define gc() getchar()
  14. #define fp(i,a,b) for(re int i=a;i<=b;i++)
  15. #define fq(i,a,b) for(re int i=a;i>=b;i--)
  16. using namespace std;
  17. const int N=1644;
  18. int n,m,q,sx,sy,rx,ry,dfn[N*N],low[N*N],top,sta[N*N],tot,Id[N][N];
  19. int mx[4]={1,-1,0,0},my[4]={0,0,1,-1};
  20. bool f[4][N][N],vis[N][N];
  21. char mp[N][N];
  22. struct dat{int x,y,w;};
  23. queue<dat>Q;
  24. vector<int>c[N*N];
  25. il int id(re int x,re int y){return Id[x][y];}
  26. il int gi()
  27. {
  28. re int x=0,t=1;
  29. re char ch=getchar();
  30. while(ch!='-'&&(ch<'0'||ch>'9')) ch=gc();
  31. if(ch=='-') t=-1,ch=gc();
  32. while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=gc();
  33. return x*t;
  34. }
  35. il void Tarjan(re int x,re int y,re int fx,re int fy)
  36. {
  37. re int u=id(x,y);
  38. sta[++top]=u,dfn[u]=low[u]=++tot;
  39. fp(i,0,3)
  40. {
  41. re int xx=x+mx[i],yy=y+my[i],v=id(xx,yy);
  42. if(mp[xx][yy]=='#') continue;
  43. if(xx==fx&&yy==fy) continue;
  44. if(!dfn[v])
  45. {
  46. Tarjan(xx,yy,x,y);
  47. low[u]=min(low[u],low[v]);
  48. if(low[v]>=dfn[u])
  49. {
  50. ++tot;re int g;
  51. do{g=sta[top--];c[g].pb(tot);}while(g^v);
  52. c[u].pb(tot);
  53. }
  54. }
  55. else low[u]=min(low[u],dfn[v]);
  56. }
  57. }
  58. il void BFS1()
  59. {
  60. Q.push((dat){rx,ry,0});vis[rx][ry]=1;
  61. while(!Q.empty())
  62. {
  63. re int x=Q.front().x,y=Q.front().y,u=id(x,y);Q.pop();
  64. fp(i,0,3)
  65. {
  66. re int xx=x+mx[i],yy=y+my[i],v=id(xx,yy);
  67. if(mp[xx][yy]=='#'||vis[xx][yy]) continue;
  68. if(xx==sx&&yy==sy) {f[i^1][xx][yy]=1;continue;}
  69. vis[xx][yy]=1;Q.push((dat){xx,yy,0});
  70. }
  71. }
  72. }
  73. il int check(re int x,re int y,re int xx,re int yy)
  74. {
  75. re int u=id(x,y),v=id(xx,yy);
  76. for(re int i=0;i<c[u].size();++i)
  77. for(re int j=0;j<c[v].size();++j)
  78. if(c[u][i]==c[v][j]) return 1;
  79. return 0;
  80. }
  81. il void BFS2()
  82. {
  83. fp(i,0,3) if(f[i][sx][sy]) Q.push((dat){sx,sy,i});
  84. while(!Q.empty())
  85. {
  86. re int x=Q.front().x,y=Q.front().y,w=Q.front().w,u=id(x,y);Q.pop();
  87. fp(i,0,3)
  88. {
  89. if(f[i][x][y]) continue;
  90. re int xx=x+mx[i],yy=y+my[i];
  91. if(mp[xx][yy]=='#') continue;
  92. if(check(x+mx[w],y+my[w],xx,yy)) f[i][x][y]=1,Q.push((dat){x,y,i});
  93. }
  94. {
  95. re int xx=x+mx[w^1],yy=y+my[w^1];///yy=y+mx???????
  96. if(mp[xx][yy]=='#') continue;
  97. if(!f[w][xx][yy]) f[w][xx][yy]=1,Q.push((dat){xx,yy,w});
  98. }
  99. }
  100. }
  101. int main()
  102. {
  103. n=gi();m=gi();q=gi();
  104. memset(mp,'#',sizeof(mp));
  105. fp(i,1,n) scanf("%s",mp[i]+1),mp[i][m+1]='#';
  106. fp(i,1,n)
  107. fp(j,1,m)
  108. {
  109. if(mp[i][j]=='A') rx=i,ry=j,mp[i][j]='.';
  110. else if(mp[i][j]=='B') sx=i,sy=j,mp[i][j]='.';
  111. Id[i][j]=(i-1)*m+j;
  112. }
  113. Tarjan(rx,ry,0,0);
  114. BFS1();
  115. BFS2();
  116. while(q--)
  117. {
  118. re int x=gi(),y=gi(),tag=(sx==x&&sy==y);
  119. fp(i,0,3) tag|=f[i][x][y];
  120. puts(tag?"YES":"NO");
  121. }
  122. return 0;
  123. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注