POI1999.Store-keeper(推箱子)——点双连通分量+割点+bfs
来源:互联网 发布:淘宝不为人知的好东西 编辑:程序博客网 时间:2024/06/11 14:14
http://www.bnuoj.com/v3/problem_show.php?pid=21155
题目描述:
有一个n*m的地图,S表示墙,w表示空地,P表示箱子的起始位置,K表示目标位置,M表示人的起始位置
求把箱子从起始位置推到目标位置所需要的最小步数
分析:
https://www.byvoid.com/blog/poi-1999-mag/
byvoid大牛解析
无限wa,郁闷
//并不能AC#include <iostream>#include <cstring>#include <cstdio>#include <algorithm>#include <cstdlib>#include <queue>#define clr(a,b) memset(a,b,sizeof(a))#define rep(i,n) for(int i=0;i<(n);++i)#define rep1(i,a,b) for(int i=(a);i<(b);++i)#define For(i,n) for(int i=0;i<=(n);++i)#define For1(i,a,b) for(int i=(a);i<=(b);++i)#define forever for(;;)const int MAXN = 10010;const int MAXM = 10010;using namespace std;int n,m;char pic[110][110];struct Tarjan { int low[MAXN],dfn[MAXN],Stack[MAXN],Belong[MAXN]; int top,block; bool iscut[MAXN]; struct Edge { int to,Next; } edge[MAXM<<1];int head[MAXN],tot; void addedge(int u,int v) { edge[tot].to=v; edge[tot].Next=head[u]; head[u]=tot++; } void init() { tot=0; clr(head,0xff); } void dfs(int u,int pre,int dth) { int v; low[u]=dfn[u]=dth; Stack[top++]=u; int son=0; for(int i=head[u]; i!=-1; i=edge[i].Next) { v=edge[i].to; if(v==pre) continue; if(!dfn[v]) { son++; dfs(v,u,dth+1); if(low[u]>low[v]) low[u]=low[v]; if(low[v]>=dfn[u]) { iscut[u]=true; block++; int vn; forever { vn=Stack[--top]; Belong[vn]=block; if(vn==v) break; } } } else if(low[u]>dfn[v]) low[u]=dfn[v]; } if(pre<0&&son==1) iscut[u]=false; } void solve() { clr(dfn,0); clr(iscut,false); top=block=0; rep(i,n*m) { if(!dfn[i]) dfs(i,-1,1); } }}bcc;struct node { int x,y;};struct state{ node box,h; int st; bool operator<(const state&a)const{ return st>a.st; }};state cur,Next;bool Hash[110][110][4];int dx[]={0,0,1,-1};int dy[]={1,-1,0,0};int sx,sy;bool isnode(int i,int j){ if(pic[i][j]=='w'||pic[i][j]=='P'||pic[i][j]=='M') return true; return false;}bool isok(int x,int y){ if(x>=0&&x<n&&y>=0&&y<m&&pic[x][y]!='S') return true; return false;}bool getHash(state cur,int i){ return Hash[cur.box.x][cur.box.y][i];}void setHash(state cur,int i){ Hash[cur.box.x][cur.box.y][i]=true;}bool find(state cur){ if(pic[cur.box.x][cur.box.y]=='K') return true; return false;}bool is_together(int x1,int y1,int x2,int y2){ if(bcc.Belong[x1*n+y1]==bcc.Belong[x2*n+y2]) return true; return false;}int box_tonode(state x){ return x.box.x*n+x.box.y;}int h_tonode(state x){ return x.h.x*n+x.h.y;}int fa[MAXN];int find(int x){ return x==fa[x]? x:fa[x]=find(fa[x]);}void unionSet(int a,int b){ int p=find(a),q=find(b); if(p!=q) fa[p]=q;}int bfs(){ priority_queue<state> q; q.push(cur); clr(Hash,false); int u,v; while(!q.empty()){ cur=q.top();q.pop(); if(find(cur)) return cur.st; rep(i,4){ Next=cur; Next.box.x=cur.box.x+dx[i]; Next.box.y=cur.box.y+dy[i]; Next.st=cur.st+1; if(!isok(Next.box.x,Next.box.y)) continue; if(!bcc.iscut[box_tonode(cur)]){ u=h_tonode(cur),v=(cur.box.x-dx[i])*n+cur.box.y-dy[i]; if(find(u)!=find(v)) continue; if(!getHash(Next,i)){ Next.h.x=cur.box.x; Next.h.y=cur.box.y; setHash(Next,i); q.push(Next); } } else{ if(!is_together(cur.h.x,cur.h.y,cur.box.x-dx[i],cur.box.y-dy[i])) continue; if(!getHash(Next,i)){ Next.h.x=cur.box.x; Next.h.y=cur.box.y; setHash(Next,i); q.push(Next); } } } } return -1;}int main(){#ifndef ONLINE_JUDGEfreopen("in.cpp","r",stdin);#endif // ONLINE_JUDGE int T,u,v,un,vn; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); bcc.init(); For1(i,1,n*m){ fa[i]=i; } rep(i,n) scanf("%s",pic[i]); rep(i,n)rep(j,m-1) { if(pic[i][j]=='P'){ cur.box.x=i;cur.box.y=j; cur.st=0; } if(pic[i][j]=='M'){ cur.h.x=i,cur.h.y=j; } if(isnode(i,j) && isnode(i,j+1)) { u = i*n+j,v = i*n+j+1; unionSet(u,v); bcc.addedge(u,v); bcc.addedge(v,u); } } rep(i,m)rep(j,n-1) { if(isnode(j,i)&&isnode(j+1,i)) { u=j*n+i,v=(j+1)*n+i; unionSet(u,v); bcc.addedge(u,v); bcc.addedge(v,u); } } bcc.solve(); int ans=bfs(); if(ans==-1) puts("NO"); else printf("%d\n",ans); } return 0;}
0 0
- POI1999.Store-keeper(推箱子)——点双连通分量+割点+bfs
- 【poi9911】Store-Keeper wdata(BFS+点双连通分量)
- 割点、桥、双连通分量
- 割点 桥 双连通分量模版
- POJ 1523 SPF (割顶 点双连通分量)
- 点双连通分量
- 点双连通分量
- 点双连通分量
- 点双连通分量
- 图论-桥/割点/双连通分量/缩点/LCA
- hdu 3394 Railway【点双连通分量、桥、割点】
- 割点、割边和双连通分量
- bzoj2730 [HNOI2012]矿场搭建 ( 割点 & 点双连通分量 )
- 无向连通图的割点,割边(桥),双连通分量。
- tarjan算法应用 割点 桥 双连通分量
- 割点,桥,双连通分量Tarjan ,入门练习
- tarjan算法应用 割点 桥 双连通分量
- tarjan算法应用 割点 桥 双连通分量
- Android 开发环境下载地址 -- 百度网盘 adt-bundle android-studio sdk adt 下载
- Android中Service的详细解释与使用(附源码)
- 拿到6个重磅offer的大神,超详细面试经验总结
- 01 _04 R语言概览
- 理解SVM的三层境界
- POI1999.Store-keeper(推箱子)——点双连通分量+割点+bfs
- POP3协议分析
- Android中socket的实例分析(二)
- HICON 保存为.ICO
- PythonChallenge第9题
- hdu 2818 Building Block
- C++中 虚函数中的默认参数问题
- 单例设计模式
- adb architecture