1. 程式人生 > >NOIP2013華容道(BFS+亂搞)

NOIP2013華容道(BFS+亂搞)

最小步數 bsp 最小 移動 nbsp tag cstring emp ret

n<=30 * m<=30 的地圖上,0表示墻壁,1表示可以放箱子的空地。q<=500次詢問,每次問:當空地上唯一沒有放箱子的空格子在(ex,ey)時,把位於(sx,sy)的箱子移動到(tx,ty)的最小步數。

Solution

一開始聽說這道題很難,所以剛拿到題就開始打暴力,emmm。。。

比較native的思路是記錄當前點的位置和空白點的位置,然後暴力轉移。

但這個狀態十分沒有必要,因為我的位置能動的前提是空格在我的當前位置的旁邊。

所以我們把狀態變成當前點的位置和空白點在當前點的什麽方位。

但轉移變得困難了,因為我還需要知道從一個點到另一個點不經過某個點的最短距離。

於是就不會了,滾去看TJ。

發現不能經過的點就在當前點的旁邊。

所以我們n^2*m^2*4的預處理出這個東西。

但初始狀態怎麽搞?不能經過的點不在起點旁邊啊?

考慮暴力處理這個問題。

發現能過2333

註意判0的情況。

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<cstdlib>
#include<cmath>
#define R register
#define mm make_pair
using namespace std;
const int dx[4]={0,0,-1,1}; const int dy[4]={1,-1,0,0}; struct node{ int x,y,tag; }; queue<node>q; queue<pair<int,int> >que; int a[32][32],ex,ey,sx,sy,tx,ty,n,m,qu,dis[32][32][4],ans,mi[32][32][4][32][32],ji[5],di[32][32]; bool vis[32][32][4],visi[32][32]; inline int rd(){ int
x=0;char c=getchar();while(!isdigit(c))c=getchar(); while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();} return x; } inline void BFS(int ii,int jj,int x2,int y2,int tag){ que.push(mm(ii,jj)); mi[ii][jj][tag][ii][jj]=0; while(!que.empty()){ int u1=que.front().first,u2=que.front().second;visi[u1][u2]=0;que.pop(); for(int i=0;i<4;++i){ int v1=u1+dx[i],v2=u2+dy[i]; if((v1==x2&&v2==y2)||!a[v1][v2])continue; if(mi[ii][jj][tag][v1][v2]>mi[ii][jj][tag][u1][u2]+1){ mi[ii][jj][tag][v1][v2]=mi[ii][jj][tag][u1][u2]+1; if(!visi[v1][v2]){ visi[v1][v2]=1; que.push(mm(v1,v2)); } } } } } inline void BB(int ii,int jj,int x2,int y2){ que.push(mm(ii,jj)); memset(di,0x3f,sizeof(di)); di[ii][jj]=0; while(!que.empty()){ int u1=que.front().first,u2=que.front().second;visi[u1][u2]=0;que.pop(); for(int i=0;i<4;++i){ int v1=u1+dx[i],v2=u2+dy[i]; if((v1==x2&&v2==y2)||!a[v1][v2])continue; if(di[v1][v2]>di[u1][u2]+1){ di[v1][v2]=di[u1][u2]+1; if(!visi[v1][v2]){ visi[v1][v2]=1; que.push(mm(v1,v2)); } } } } } int main(){ n=rd();m=rd();qu=rd();ji[0]=1;ji[3]=2;ji[1]=0;ji[2]=3; memset(mi,0x3f,sizeof(mi)); for(R int i=1;i<=n;++i)for(R int j=1;j<=m;++j)a[i][j]=rd(); for(R int i=1;i<=n;++i) for(R int j=1;j<=m;++j) for(R int k=0;k<4;++k)BFS(i,j,i+dx[k],j+dy[k],k); while(qu--){ ex=rd();ey=rd();sx=rd();sy=rd();tx=rd();ty=rd(); if(tx==sx&&ty==sy){ printf("0\n"); continue; } memset(dis,0x3f,sizeof(dis)); for(int i=0;i<4;++i){ int xx=sx+dx[i],yy=sy+dy[i]; BB(ex,ey,sx,sy); if(di[xx][yy]!=0x3f3f3f3f){ q.push(node{sx,sy,i}); dis[sx][sy][i]=di[xx][yy]; } } ans=0x7f7f7f7f; while(!q.empty()){ node u=q.front();q.pop();vis[u.x][u.y][u.tag]=0; if(u.x==tx&&u.y==ty){ ans=min(ans,dis[u.x][u.y][u.tag]); continue; } for(R int i=0;i<4;++i){ R int xx=u.x+dx[i],yy=u.y+dy[i]; if(!a[xx][yy])continue; int x=u.x+dx[u.tag],y=u.y+dy[u.tag],z=mi[x][y][ji[u.tag]][xx][yy]+1; if(dis[xx][yy][ji[i]]>dis[u.x][u.y][u.tag]+z){ dis[xx][yy][ji[i]]=dis[u.x][u.y][u.tag]+z; if(!vis[xx][yy][ji[i]]){ vis[xx][yy][ji[i]]=1; q.push(node{xx,yy,ji[i]}); } } } } if(ans!=0x7f7f7f7f)printf("%d\n",ans); else printf("-1\n"); } return 0; }

NOIP2013華容道(BFS+亂搞)