BZOJ 2574: [Poi1999]Store-Keeper
Description
推箱子. \(n,m\leqslant 100\)
Sol
Tarjan+边双连通分量+BFS.
直接搜索的复杂度是 \(n^6\) 记录人的位置,箱子的位置和转移.
箱子的位置相当于一个障碍.
先灌水,把移动到箱子周围,每次的状态都是人在箱子旁边,这样复杂度就降为了 \(4n^4\) .
每次BFS分两步,改变方向和移动箱子.
如果箱子所在位置不是割点,那么往所有方向都联通.
否则想改变方向的话,两点必须是双连通才行.
这样复杂度就降低了...判断的时候可以预处理出来.
这样判断可以变成 \(O(1)\) .但是我没有这么写,直接暴力判断两点是否有相同的双连通分量.
Code
#include<cstdio>
#include<cstring>
#include<utility>
#include<queue>
#include<vector>
#include<iostream>
using namespace std; #define debug(a) cout<<#a<<"="<<a<<" "
#define mpr make_pair
#define x first
#define y second
typedef pair< int,int > pr;
const int N = 105; int n,m,dx,dy,sx,sy,tx,ty,ans;
int id[N][N],a[N][N],isg[N*N],to[N*N][4],v[N][N],vis[N*N*4];
int dfsn[N*N],low[N*N],cnt,bcnt;
pr stk[N*N];int top;
vector< int > bl[N*N];
char s[N];
int mvx[]={ -1,1,0,0 };
int mvy[]={ 0,0,-1,1 };
struct S{ int x,y,r,d; };
queue< S > q; void Print(int a[N][N]){
cout<<"------------------------------"<<endl;
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) printf("%d%c",a[i][j]," \n"[j==m]);
}
void insert(int x,int b){
for(int i=0,lim=bl[x].size();i<lim;i++) if(bl[x][i] == b) return;
bl[x].push_back(b);
}
void Tarjan(int u,int fa){
low[u]=dfsn[u]=++cnt;
for(int i=0,xx,yy;i<4;i++) if(to[u][i] && to[u][i]!=fa){
if(!dfsn[to[u][i]]){
stk[++top]=mpr(u,to[u][i]);
Tarjan(to[u][i],u);
low[u]=min(low[u],low[to[u][i]]);
if(dfsn[u]<=low[to[u][i]]){
++bcnt,isg[u]=1;
do{
xx=stk[top].x,yy=stk[top--].y;
insert(xx,bcnt),insert(yy,bcnt);
}while(!((xx==u && yy==to[u][i]) || (xx==to[u][i] && yy==u)));
}
}else low[u]=min(low[u],dfsn[to[u][i]]);
}
}
int Move(int x,int y,int r1,int r2){
if(!a[x+mvx[r2]][y+mvy[r2]]) return 0;
int now=id[x+mvx[r1]][y+mvy[r1]],gt=id[x+mvx[r2]][y+mvy[r2]];
if(!isg[id[x][y]]) return 1;
else{
for(int i=0,j,limi=bl[now].size(),limj=bl[gt].size();i<limi;i++)
for(j=0;j<limj;j++) if(bl[now][i] == bl[gt][j]) return 1;
}return 0;
}
void Fill(int fx,int fy){
if(fx == sx && fy == sy) return;
v[fx][fy]=1;
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))
Fill(fx+mvx[i],fy+mvy[i]);
}
int BFS(){
Fill(dx,dy);
// Print(v);
for(int i=0;i<4;i++) if(a[sx+mvx[i]][sy+mvy[i]]){
// debug(sx+mvx[i]),debug(sy+mvy[i])<<endl;
if(v[sx+mvx[i]][sy+mvy[i]]) vis[id[sx][sy]<<2|i]=1,q.push((S){ sx,sy,i,0 });
}
for(S now;!q.empty();){
now=q.front(),q.pop();
// cout<<now.x<<" "<<now.y<<" "<<now.r<<" "<<now.d<<endl;
if(now.x == tx && now.y == ty) return ans=now.d,1;
for(int i=0;i<4;i++){
if(now.r!=i && Move(now.x,now.y,now.r,i) && !vis[id[now.x][now.y]<<2|i]){
vis[id[now.x][now.y]<<2|i]=1;
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]]){
vis[id[now.x+mvx[i^1]][now.y+mvy[i^1]]<<2|i]=1;
q.push((S){ now.x+mvx[i^1],now.y+mvy[i^1],i,now.d+1 });
}
}else if(now.r == i){
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]]){
vis[id[now.x+mvx[i^1]][now.y+mvy[i^1]]<<2|i]=1;
q.push((S){ now.x+mvx[i^1],now.y+mvy[i^1],i,now.d+1 });
}
}
}
}return 0;
}
int main(){
// freopen("in.in","r",stdin);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%s",s+1);
for(int j=1;j<=m;j++){
id[i][j]=i*m+j;
if(s[j] == 'S') a[i][j]=0;
else a[i][j]=1;
if(s[j] == 'M') dx=i,dy=j;
if(s[j] == 'P') sx=i,sy=j;
if(s[j] == 'K') tx=i,ty=j;
}
}
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){
if(a[i-1][j]) to[id[i][j]][0]=id[i-1][j];
if(a[i][j-1]) to[id[i][j]][1]=id[i][j-1];
if(a[i+1][j]) to[id[i][j]][2]=id[i+1][j];
if(a[i][j+1]) to[id[i][j]][3]=id[i][j+1];
}
Tarjan(id[tx][ty],0); // Print(a); if(BFS()) printf("%d\n",ans);
else puts("NO");
return 0;
}
BZOJ 2574: [Poi1999]Store-Keeper的更多相关文章
- BZOJ 2933([Poi1999]地图-区间Dp)
2933: [Poi1999]地图 Time Limit: 1 Sec Memory Limit: 128 MB Submit: 7 Solved: 7 [ Submit][ Status] ...
- BZOJ 2929: [Poi1999]洞穴攀行
2929: [Poi1999]洞穴攀行 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 351 Solved: 195[Submit][Status][ ...
- bzoj 2929 [Poi1999]洞穴攀行 网络流
2929: [Poi1999]洞穴攀行 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 499 Solved: 295[Submit][Status][ ...
- 【刷题】BZOJ 2935 [Poi1999]原始生物
Description 原始生物的遗传密码是一个自然数的序列K=(a1,...,an).原始生物的特征是指在遗传密码中连续出现的数对(l,r),即存在自然数i使得l=ai且r=ai+1.在原始生物的遗 ...
- bzoj 2927: [Poi1999]多边形之战【博弈论】
先手必胜状态是黑三角在边上 然后其他情况脑补一下,n为偶数先手必胜,可以理解为从某一边取,先手总有办法让后手取得一边有奇数个 #include<iostream> #include< ...
- BZOJ 2927: [Poi1999]多边形之战 (博弈)
题意 有一个凸多边形,顶点编号逆时针从0到n-1.现在这个n边形被剖分成n-2个三角形,给出这n-2个三角形的顶点,保证这是用n-3条不交叉的对角线划分出来的.现在第一个三角形是黑色,其他都是白色.两 ...
- bzoj 2935 [Poi1999]原始生物——欧拉回路思路!
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2935 有向图用最小的路径(==总点数最少)覆盖所有边. 完了完了我居然连1999年的题都做不 ...
- bzoj AC倒序
Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...
- 【BZOJ 2802】 2802: [Poi2012]Warehouse Store (贪心)
2802: [Poi2012]Warehouse Store Description 有一家专卖一种商品的店,考虑连续的n天.第i天上午会进货Ai件商品,中午的时候会有顾客需要购买Bi件商品,可以选择 ...
随机推荐
- 自然语言16.1_Python自然语言处理学习笔记之信息提取步骤&分块(chunking)
QQ:231469242 欢迎喜欢nltk朋友交流 http://www.cnblogs.com/undercurrent/p/4754944.html 一.信息提取模型 信息提取的步骤共分为五步,原 ...
- sqlserver插入时发生在“xxx”处关键发生错误
今天知道了一个小技巧,当你的数据库表名为user时会sqlserver的表发生冲突,所以因该将user这样用[user],ok 一切搞定 .
- Error: [$rootScope:inprog] $digest already in progress
我在 做一个 服务器分配成功以后需要更新 整个页面,我的思路是 更新成功以后,就手动的 触发一下 搜索按钮,但是在触发后,虽然成功刷新了页面,但是出现了一个 错误提示, Error: [$rootSc ...
- 使用.net Stopwatch class 来分析你的代码
当我们在调试,优化我们的代码的时候,想知道某段代码的真正的执行时间,或者我们怀疑某段代码,或是某几段代码执行比较慢, 需要得到具体的某段代码的具体执行时间的时候.有一个很好用的类Stopwatch. ...
- TCSQL实时列表缓存数据库帮助文档
[文章作者:张宴 本文版本:v1.1 最后修改:2010.09.03 转载请注明原文链接:http://blog.zyan.cc/tcsql/] 曾经有人提出,一般数据库缓存分为四种.第一种:单个对象 ...
- 昨天所写的JQ 点击隐藏事件,关键性原理
JQ 点击隐藏事件,关键性原理 1.JQ 库的调用 一般选择为: 1)库越小越好 2)库的功能越强大越好 <script src="js/jquery.js" type=&q ...
- acdream1233 Royal Federation (构造?)
http://acdream.info/problem?pid=1233 Andrew Stankevich's Contest (3) ASC 3 Royal Federation Special ...
- HTTP Basic Authentication
Client端发送请求, 要在发送请求的时候添加HTTP Basic Authentication认证信息到请求中,有两种方法:1. 在请求头中添加Authorization: Authoriz ...
- [转]Android性能优化典范
2015年伊始,Google发布了关于Android性能优化典范的专题,一共16个短视频,每个3-5分钟,帮助开发者创建更快更优秀的Android App.课程专题不仅仅介绍了Android系统中有关 ...
- CATransition-转场动画
CAAnimation的子类,用于做转场动画,能够为层提供移出屏幕和移入屏幕的动画效果.iOS比Mac OS X的转场动画效果少一点 UINavigationController就是通过CATrans ...