Description

推箱子. \(n,m\leqslant 100\)

Sol

Tarjan+边双连通分量+BFS.

直接搜索的复杂度是 \(n^6\) 记录人的位置,箱子的位置和转移.

箱子的位置相当于一个障碍.

先灌水,把移动到箱子周围,每次的状态都是人在箱子旁边,这样复杂度就降为了 \(4n^4\) .

每次BFS分两步,改变方向和移动箱子.

如果箱子所在位置不是割点,那么往所有方向都联通.

否则想改变方向的话,两点必须是双连通才行.

这样复杂度就降低了...判断的时候可以预处理出来.

这样判断可以变成 \(O(1)\) .但是我没有这么写,直接暴力判断两点是否有相同的双连通分量.

Code

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<utility>
  4. #include<queue>
  5. #include<vector>
  6. #include<iostream>
  7. using namespace std;
  8.  
  9. #define debug(a) cout<<#a<<"="<<a<<" "
  10. #define mpr make_pair
  11. #define x first
  12. #define y second
  13. typedef pair< int,int > pr;
  14. const int N = 105;
  15.  
  16. int n,m,dx,dy,sx,sy,tx,ty,ans;
  17. int id[N][N],a[N][N],isg[N*N],to[N*N][4],v[N][N],vis[N*N*4];
  18. int dfsn[N*N],low[N*N],cnt,bcnt;
  19. pr stk[N*N];int top;
  20. vector< int > bl[N*N];
  21. char s[N];
  22. int mvx[]={ -1,1,0,0 };
  23. int mvy[]={ 0,0,-1,1 };
  24. struct S{ int x,y,r,d; };
  25. queue< S > q;
  26.  
  27. void Print(int a[N][N]){
  28. cout<<"------------------------------"<<endl;
  29. for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) printf("%d%c",a[i][j]," \n"[j==m]);
  30. }
  31. void insert(int x,int b){
  32. for(int i=0,lim=bl[x].size();i<lim;i++) if(bl[x][i] == b) return;
  33. bl[x].push_back(b);
  34. }
  35. void Tarjan(int u,int fa){
  36. low[u]=dfsn[u]=++cnt;
  37. for(int i=0,xx,yy;i<4;i++) if(to[u][i] && to[u][i]!=fa){
  38. if(!dfsn[to[u][i]]){
  39. stk[++top]=mpr(u,to[u][i]);
  40. Tarjan(to[u][i],u);
  41. low[u]=min(low[u],low[to[u][i]]);
  42. if(dfsn[u]<=low[to[u][i]]){
  43. ++bcnt,isg[u]=1;
  44. do{
  45. xx=stk[top].x,yy=stk[top--].y;
  46. insert(xx,bcnt),insert(yy,bcnt);
  47. }while(!((xx==u && yy==to[u][i]) || (xx==to[u][i] && yy==u)));
  48. }
  49. }else low[u]=min(low[u],dfsn[to[u][i]]);
  50. }
  51. }
  52. int Move(int x,int y,int r1,int r2){
  53. if(!a[x+mvx[r2]][y+mvy[r2]]) return 0;
  54. int now=id[x+mvx[r1]][y+mvy[r1]],gt=id[x+mvx[r2]][y+mvy[r2]];
  55. if(!isg[id[x][y]]) return 1;
  56. else{
  57. for(int i=0,j,limi=bl[now].size(),limj=bl[gt].size();i<limi;i++)
  58. for(j=0;j<limj;j++) if(bl[now][i] == bl[gt][j]) return 1;
  59. }return 0;
  60. }
  61. void Fill(int fx,int fy){
  62. if(fx == sx && fy == sy) return;
  63. v[fx][fy]=1;
  64. for(int i=0;i<4;i++) if(a[fx+mvx[i]][fy+mvy[i]] && !v[fx+mvx[i]][fy+mvy[i]] && (fx+mvx[i]!=sx || fy+mvy[i]!=sy))
  65. Fill(fx+mvx[i],fy+mvy[i]);
  66. }
  67. int BFS(){
  68. Fill(dx,dy);
  69. // Print(v);
  70. for(int i=0;i<4;i++) if(a[sx+mvx[i]][sy+mvy[i]]){
  71. // debug(sx+mvx[i]),debug(sy+mvy[i])<<endl;
  72. if(v[sx+mvx[i]][sy+mvy[i]]) vis[id[sx][sy]<<2|i]=1,q.push((S){ sx,sy,i,0 });
  73. }
  74. for(S now;!q.empty();){
  75. now=q.front(),q.pop();
  76. // cout<<now.x<<" "<<now.y<<" "<<now.r<<" "<<now.d<<endl;
  77. if(now.x == tx && now.y == ty) return ans=now.d,1;
  78. for(int i=0;i<4;i++){
  79. if(now.r!=i && Move(now.x,now.y,now.r,i) && !vis[id[now.x][now.y]<<2|i]){
  80. vis[id[now.x][now.y]<<2|i]=1;
  81. if(!vis[id[now.x+mvx[i^1]][now.y+mvy[i^1]]<<2|i] && a[now.x+mvx[i^1]][now.y+mvy[i^1]]){
  82. vis[id[now.x+mvx[i^1]][now.y+mvy[i^1]]<<2|i]=1;
  83. q.push((S){ now.x+mvx[i^1],now.y+mvy[i^1],i,now.d+1 });
  84. }
  85. }else if(now.r == i){
  86. if(!vis[id[now.x+mvx[i^1]][now.y+mvy[i^1]]<<2|i] && a[now.x+mvx[i^1]][now.y+mvy[i^1]]){
  87. vis[id[now.x+mvx[i^1]][now.y+mvy[i^1]]<<2|i]=1;
  88. q.push((S){ now.x+mvx[i^1],now.y+mvy[i^1],i,now.d+1 });
  89. }
  90. }
  91. }
  92. }return 0;
  93. }
  94. int main(){
  95. // freopen("in.in","r",stdin);
  96. scanf("%d%d",&n,&m);
  97. for(int i=1;i<=n;i++){
  98. scanf("%s",s+1);
  99. for(int j=1;j<=m;j++){
  100. id[i][j]=i*m+j;
  101. if(s[j] == 'S') a[i][j]=0;
  102. else a[i][j]=1;
  103. if(s[j] == 'M') dx=i,dy=j;
  104. if(s[j] == 'P') sx=i,sy=j;
  105. if(s[j] == 'K') tx=i,ty=j;
  106. }
  107. }
  108. for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){
  109. if(a[i-1][j]) to[id[i][j]][0]=id[i-1][j];
  110. if(a[i][j-1]) to[id[i][j]][1]=id[i][j-1];
  111. if(a[i+1][j]) to[id[i][j]][2]=id[i+1][j];
  112. if(a[i][j+1]) to[id[i][j]][3]=id[i][j+1];
  113. }
  114. Tarjan(id[tx][ty],0);
  115.  
  116. // Print(a);
  117.  
  118. if(BFS()) printf("%d\n",ans);
  119. else puts("NO");
  120. return 0;
  121. }

  

BZOJ 2574: [Poi1999]Store-Keeper的更多相关文章

  1. BZOJ 2933([Poi1999]地图-区间Dp)

    2933: [Poi1999]地图 Time Limit: 1 Sec   Memory Limit: 128 MB Submit: 7   Solved: 7 [ Submit][ Status] ...

  2. BZOJ 2929: [Poi1999]洞穴攀行

    2929: [Poi1999]洞穴攀行 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 351  Solved: 195[Submit][Status][ ...

  3. bzoj 2929 [Poi1999]洞穴攀行 网络流

    2929: [Poi1999]洞穴攀行 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 499  Solved: 295[Submit][Status][ ...

  4. 【刷题】BZOJ 2935 [Poi1999]原始生物

    Description 原始生物的遗传密码是一个自然数的序列K=(a1,...,an).原始生物的特征是指在遗传密码中连续出现的数对(l,r),即存在自然数i使得l=ai且r=ai+1.在原始生物的遗 ...

  5. bzoj 2927: [Poi1999]多边形之战【博弈论】

    先手必胜状态是黑三角在边上 然后其他情况脑补一下,n为偶数先手必胜,可以理解为从某一边取,先手总有办法让后手取得一边有奇数个 #include<iostream> #include< ...

  6. BZOJ 2927: [Poi1999]多边形之战 (博弈)

    题意 有一个凸多边形,顶点编号逆时针从0到n-1.现在这个n边形被剖分成n-2个三角形,给出这n-2个三角形的顶点,保证这是用n-3条不交叉的对角线划分出来的.现在第一个三角形是黑色,其他都是白色.两 ...

  7. bzoj 2935 [Poi1999]原始生物——欧拉回路思路!

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2935 有向图用最小的路径(==总点数最少)覆盖所有边. 完了完了我居然连1999年的题都做不 ...

  8. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  9. 【BZOJ 2802】 2802: [Poi2012]Warehouse Store (贪心)

    2802: [Poi2012]Warehouse Store Description 有一家专卖一种商品的店,考虑连续的n天.第i天上午会进货Ai件商品,中午的时候会有顾客需要购买Bi件商品,可以选择 ...

随机推荐

  1. linux中快速清空文件内容的几种方法

    这篇文章主要介绍了linux中快速清空文件内容的几种方法,需要的朋友可以参考下 $ : > filename $ > filename $ echo "" > f ...

  2. Unity逻辑热更新

    http://www.xuanyusong.com/archives/3075 http://www.unitymanual.com/thread-36503-1-1.html http://www. ...

  3. thinkphp模板引擎

    $this->assing('result'.$result) html页面代码 <foreach name='result item='vo'> <div>{$vo[' ...

  4. 创建menu文件

    一.问题: android studio项目中没有看到menu文件夹: 在android studio项目中想要添加menu布局文件,一开始我的做法是:直接在res文件夹右键选择xml文件来添加,如下 ...

  5. C# 实现 Snowflake算法 ID生成

    http://blog.csdn.net/w200221626/article/details/52064976 C# 实现 Snowflake算法 /// <summary> /// 动 ...

  6. 序列化与反序列化成XML

    http://blog.itpub.net/12639172/viewspace-490786/ 现在XML都普遍的用到了很多地方,它的平台无关.方便.结构化.适用性的特点让人不得不去接受它,在C#中 ...

  7. Redis-cluster集群【第一篇】:redis安装及redis数据类型

    Redis介绍: 一.介绍 redis 是一个开源的.使用C语言编写的.支持网络交互的.可以基于内存也可以持久化的Key-Value数据库. redis的源码非常简单,只要有时间看看谭浩强的C语言,在 ...

  8. 负margin小记

    static元素  margin-top/left负值,元素向指定方向移动,               margin-bottom/right负值,元素不动,后续元素前移 float元素   左浮, ...

  9. 使用ab压测网页结果分析

    使用ab压测网页结果分析 下载工具:ab 图片来自:http://my.oschina.net/u/1246814/blog/291696?fromerr=JfLeu1jk

  10. 使用Struts 2框架实现文件下载

    从服务器发送一个文件到浏览器需要以下几个步骤 把HTTP响应里的ContentType标头设置为被下载文件的内容类型.ContentType标头的作用是表明数据包里的数据是什么类型, 它由一个多媒体类 ...