noip2013day2T3华容道
这道题,写的很醉啊。。。。
这种搜索的题,还带一点DP,各种bug调了好久,
思路:
60分做法就直接bfs乱搞,60分到手;
ac套路:
首先预处理出f[i][j][k]状态,对于点ij,空格在k方向就是开个【30】【30】【4】的数组,再用邻接表存下来,spfa跑一边最短路就好了,注意终点和起点是可能重合的;
code:
#include<cstdio> #include<cstring> #include<iostream> #include<queue> #include<algorithm> const int N=35; const int M=400010; const int inf=1000000000; using namespace std; bool vis[N][N]; const int d[4][2]={{-1, 0}, {1, 0}, {0, -1}, {0, 1}}; struct point{ int x, y, d; }; int n,m,q,map[N][N]; int bfs(int x1, int y1, int x2, int y2){ for(int i=1; i<=n; ++i) for(int j=1; j<=m; ++j)vis[i][j]=false; vis[x1][y1]=true; queue<point>q; q.push((point){x1, y1, 0}); while(!q.empty()){ int x=q.front().x,y=q.front().y,dd=q.front().d; if(x==x2 && y==y2)return dd; q.pop(); for(int i=0;i<=3;++i){ int u=x+d[i][0]; int v=y+d[i][1]; if(map[u][v] && !vis[u][v]){ vis[u][v]=1; q.push((point){u,v,dd+1}); } } } return inf; } int start[M],nxt[M],to[M],w[M],e; void add(int x, int y, int z){ to[++e]=y; nxt[e]=start[x]; start[x]=e; w[e]=z; } int f[N][N][4],cnt; void pre(){ for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) for(int k=0;k<=3;++k) f[i][j][k]=++cnt; int t; for(int i=1;i<=n;++i) for(int j=1;j<=m;++j){ if(map[i][j])map[i][j]=0;else continue; for(int k=0;k<=3;++k) for(int l=0;l<=3;++l){ int x1=i+d[k][0],y1=j+d[k][1],x2=i+d[l][0],y2=j+d[l][1]; if(map[x1][y1] && map[x2][y2]){ t=bfs(x1,y1,x2,y2); if(t<inf)add(f[i][j][k],f[x2][y2][l^1],t+1); } } map[i][j]=1; } } int p[M],dis[M]; int spfa(int s,int t){ queue<int>q; for(int i=1;i<=cnt;++i)dis[i]=inf,p[i]=0; p[s]=1; q.push(s); dis[s]=0; while(!q.empty()){ int u=q.front(); p[u]=0; q.pop(); for(int i=start[u];i;i=nxt[i]){ int v=to[i]; if(dis[v]>dis[u]+w[i]){ dis[v]=dis[u]+w[i]; if(!p[v])q.push(v); p[v]=1; } } } return dis[t]<inf?dis[t]:-1; } int main(){ int x,y,x1,y1,x2,y2,t; scanf("%d%d%d",&n,&m,&q); for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) scanf("%d",&map[i][j]); pre(); for(int i=1;i<=q;++i){ int S=++cnt,T=++cnt; scanf("%d%d%d%d%d%d",&x,&y,&x1,&y1,&x2,&y2); if(x1==x2 && y1==y2){ puts("0");continue; } if(!map[x1][y1] || !map[x2][y2]){ puts("-1"); continue; } map[x1][y1]=0; //搜索出空格的移动状态 for(int j=0;j<=3;++j){ int u=x1+d[j][0],v=y1+d[j][1]; if(map[u][v]){ int t=bfs(x, y, u, v); if(t < inf)add(S, f[x1][y1][j], t); } } map[x1][y1]=1; for(int j=0;j<=3;++j){ int u=x2+d[j][0],v=y2+d[j][1]; if(map[u][v])add(f[x2][y2][j], T, 0); } printf("%d\n",spfa(S,T)); } }