显示代码纯文本
- /*
- * Problem: POI1999 mag
- * Author: Guo Jiabao
- * Time: 2009.4.7 20:54
- * State: Unsolved
- * Memo: BFS 双连通分支判断
- */
- #include <iostream>
- #include <cstdio>
- #include <cstdlib>
- #include <cmath>
- #include <cstring>
- const int MAXL=101,MAXN=10001,MAXM=MAXN*8;
- const int LEFT=0,RIGHT=1,UP=2,DOWN=3;
- const int dx[4]={0,0,-1,1},dy[4]={-1,1,0,0};
- using namespace std;
- struct state
- {
- int x,y,p,step;
- };
- template<typename T> class linklist
- {
- public:
- T v;
- linklist *next;
- linklist(T tv):v(tv){next=0;}
- };
- template<typename T> class Queue
- {
- public:
- linklist<T> *first,*last;
- int size;
- void clear()
- {
- size=0;
- first=last=0;
- }
- void ins(T v)
- {
- size++;
- if (first)
- last=last->next=new linklist<T>(v);
- else
- first=last=new linklist<T>(v);
- }
- T pop()
- {
- T r=first->v;
- linklist<T> *t=first->next;
- size--;
- delete first;
- first=t;
- return r;
- }
- };
- struct edge
- {
- edge *next;
- int t;
- }ES[MAXM];
- edge *V[MAXN];
- bool field[MAXL][MAXL],vis[MAXL][MAXL];
- bool hash[MAXL][MAXL][4];
- int mvb[MAXL][MAXL][4][4],Map[MAXL][MAXL];
- int LOW[MAXN],DFN[MAXN],PAR[MAXN],Sta1[MAXM],Sta2[MAXM],Stop,D,Bcnt;
- bool isgd[MAXN],bichash[MAXN];
- int N,M,Ans,EC=-1,U;
- state S,P,T;
- Queue<state> Q;
- Queue<int> Bel[MAXN];
- inline bool inrange(int x,int y)
- {
- return x>=1 && x<=N && y>=1 && y<=M;
- }
- inline void addedge(int a,int b)
- {
- ES[++EC].next=V[a];
- V[a]=ES+EC;V[a]->t=b;
- ES[++EC].next=V[b];
- V[b]=ES+EC;V[b]->t=a;
- }
- void init()
- {
- int i,j,k,l;
- char c;
- freopen("mag.in","r",stdin);
- freopen("mag.out","w",stdout);
- scanf("%d%d",&N,&M);
- for (i=1;i<=N;i++)
- {
- do c=getchar(); while (c==10 || c==13);
- ungetc(c,stdin);
- for (j=1;j<=M;j++)
- {
- c=getchar();
- if (c=='S')
- field[i][j]=false;
- else
- {
- field[i][j]=true;
- Map[i][j]=++U;
- k=i-1,l=j;
- if (inrange(k,l) && field[k][l])
- addedge(Map[i][j],Map[k][l]);
- k=i,l=j-1;
- if (inrange(k,l) && field[k][l])
- addedge(Map[i][j],Map[k][l]);
- }
- if (c=='M')
- {
- S.x=i;S.y=j;
- S.step=0;S.p=0;
- }
- if (c=='P')
- P.x=i,P.y=j;
- if (c=='K')
- T.x=i,T.y=j;
- for (k=0;k<4;k++)
- for (l=0;l<4;l++)
- mvb[i][j][k][l]=2;
- }
- }
- }
- inline int getopd(int k)
- {
- if (k==LEFT) return RIGHT;
- if (k==RIGHT) return LEFT;
- if (k==UP) return DOWN;
- return UP;
- }
- bool start(state i)
- {
- int k,r;
- for (k=0;k<4;k++)
- {
- state j;
- j.x=i.x+dx[k]; j.y=i.y+dy[k];
- if (inrange(j.x,j.y) && field[j.x][j.y] && !vis[j.x][j.y])
- {
- vis[j.x][j.y]=true;
- if (j.x==P.x && j.y==P.y)
- {
- P.p=getopd(k);
- return true;
- }
- else
- r=start(j);
- if (r) return true;
- }
- }
- return false;
- }
- inline bool insamebic(int u,int v)
- {
- linklist<int> *k;
- bool rs=false;
- for (k=Bel[u].first;k;k=k->next)
- bichash[k->v]=true;
- for (k=Bel[v].first;k;k=k->next)
- if (bichash[k->v])
- {
- rs=true;
- break;
- }
- for (k=Bel[u].first;k;k=k->next)
- bichash[k->v]=false;
- return rs;
- }
- bool movable(int bx,int by,int ps,int pd)
- {
- if (mvb[bx][by][ps][pd]==2)
- {
- if (isgd[Map[bx][by]])
- {
- int k=ps,x,y;
- state p,q;
- p.x=bx+dx[k]; p.y=by+dy[k];
- k=pd;
- q.x=bx+dx[k]; q.y=by+dy[k];
- x=Map[p.x][p.y]; y=Map[q.x][q.y];
- mvb[bx][by][ps][pd]=insamebic(x,y);
- }
- else
- mvb[bx][by][ps][pd]=true;
- }
- return mvb[bx][by][ps][pd];
- }
- bool BFS()
- {
- state i,j;
- int k;
- Q.clear();
- Q.ins(P);
- hash[P.x][P.y][P.p]=true;
- while (Q.size)
- {
- i=j=Q.pop();
- // printf("(%d,%d)\n",Map[i.x][i.y],i.p);
- //move direction
- for (k=0;k<4;k++)
- {
- j.x=i.x+dx[k]; j.y=i.y+dy[k];
- if (inrange(j.x,j.y) && field[j.x][j.y])
- {
- j.x=i.x;j.y=i.y;j.p=k;
- if (!hash[j.x][j.y][j.p] && movable(i.x,i.y,i.p,j.p))
- {
- hash[j.x][j.y][j.p]=true;
- Q.ins(j);
- }
- }
- }
- j.step=i.step+1;
- //push box
- k=getopd(i.p);
- j.x=i.x+dx[k]; j.y=i.y+dy[k]; j.p=i.p;
- if (inrange(j.x,j.y) && field[j.x][j.y] && !hash[j.x][j.y][j.p])
- {
- if (j.x==T.x && j.y==T.y)
- {
- Ans=j.step;
- return true;
- }
- hash[j.x][j.y][j.p]=true;
- Q.ins(j);
- }
- }
- return false;
- }
- void addbic(int B,int u)
- {
- linklist<int> *k;
- for (k=Bel[u].first;k;k=k->next)
- if (k->v==B)
- return;
- Bel[u].ins(B);
- }
- void bic(int u,int p)
- {
- DFN[u]=LOW[u]=++D;
- for (edge *k=V[u];k;k=k->next)
- {
- int v=k->t;
- if (v==p) continue;
- if (DFN[v]<DFN[u]) //避免横叉边
- {
- Stop++;Sta1[Stop]=u;Sta2[Stop]=v;
- if (!DFN[v])
- {
- bic(v,u);
- if (LOW[v]<LOW[u])
- LOW[u]=LOW[v];
- if (DFN[u]<=LOW[v])
- {
- isgd[u]=true;
- int x,y;
- Bcnt++;
- do
- {
- x=Sta1[Stop];y=Sta2[Stop];
- Stop--;
- addbic(Bcnt,x);
- addbic(Bcnt,y);
- }
- while (!(x==u && y==v || x==v && y==u));
- }
- }
- else if (DFN[v]<LOW[u])
- LOW[u]=DFN[v];
- }
- }
- }
- void solve()
- {
- bic(1,0);
- if (start(S) && BFS())
- printf("%d\n",Ans);
- else
- printf("NIE\n");
- }
- int main()
- {
- init();
- solve();
- return 0;
- }