HZOJ 走格子
作者的正解:
对于100%的数据:行动可以分为两种:
1. 步行,花费一个单位的时间移动到4联通的相邻格子中去.
2. 使用传送门,指定一个方向的墙的前面的一个格子,步行至最近的一个墙的面前,使用传送门传送.花费的时间为到达最近墙面前花费的时间+1.
两种行动相组合即可组成任意行动过程.那BFS求出最近的墙的距离,预处理上下左右的第一面墙前的格子.然后建图用DJ跑最短路即可.复杂度为O(MNlog(NM))。
其实所的很清楚了,只是不知道bfs是个什么玩意……直接$n^3$暴扫就行了呀。倒真的没什么可说的,看代码吧。
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<queue> 5 #define MP(a,b) make_pair(a,b) 6 #define ma(x,y) memset(x,y,sizeof(x)) 7 #define LL long long 8 #define INF 1000000 9 using namespace std; 10 struct edge 11 { 12 int u,v,w,nxt; 13 #define u(x) ed[x].u 14 #define v(x) ed[x].v 15 #define w(x) ed[x].w 16 #define n(x) ed[x].nxt 17 }ed[5000000]; 18 int first[300000],num_e; 19 #define f(x) first[x] 20 char map[510][510]; 21 int up[510][510],un[510][510]; 22 int le[510][510],re[510][510]; 23 int n,m; 24 int cx,cy,fx,fy; 25 inline int get(int i,int j){return (i-1)*m+j;} 26 inline pair<int,int> ret(int val){return MP(val/m+1,val%m);} 27 int dis[300010]; 28 bool v[300000]; 29 void dist(int st) 30 { 31 ma(dis,0x7f); 32 priority_queue<pair<int,int> >q; 33 dis[st]=0;q.push(MP(0,st)); 34 while(!q.empty()) 35 { 36 int x=q.top().second;q.pop(); 37 if(v[x])continue;v[x]=1; 38 for(int i=f(x);i;i=n(i)) 39 if(dis[x]+w(i)<dis[v(i)]) 40 dis[v(i)]=dis[x]+w(i), 41 q.push(MP(-dis[v(i)],v(i))); 42 } 43 } 44 inline void add(int u,int v,int w); 45 signed main() 46 { 47 cin>>n>>m; 48 for(int i=1;i<=n;i++) 49 scanf("%s",map[i]+1); 50 for(int i=1;i<=n;i++) 51 for(int j=1;j<=m;j++) 52 { 53 if(map[i][j]=='C')cx=i,cy=j; 54 if(map[i][j]=='F')fx=i,fy=j; 55 if(map[i][j]=='#') 56 up[i][j]=un[i][j]=le[i][j]=re[i][j]=INF; 57 else 58 { 59 for(int k=i-1;k>0;k--)//上 60 if(map[k][j]=='#'){up[i][j]=k+1;break;} 61 for(int k=i+1;k<=n;k++)//下 62 if(map[k][j]=='#'){un[i][j]=k-1;break;} 63 for(int k=j-1;k>0;k--)//左 64 if(map[i][k]=='#'){le[i][j]=k+1;break;} 65 for(int k=j+1;k<=m;k++)//右 66 if(map[i][k]=='#'){re[i][j]=k-1;break;} 67 } 68 } 69 for(int i=1;i<=n;i++) 70 for(int j=1;j<=m;j++) 71 if(map[i][j]!='#') 72 { 73 if(map[i-1][j]!='#')add(get(i,j),get(i-1,j),1);//,add(get(i-1,j),get(i,j),1);//上 74 if(map[i+1][j]!='#')add(get(i,j),get(i+1,j),1);//,add(get(i+1,j),get(i,j),1);//下 75 if(map[i][j-1]!='#')add(get(i,j),get(i,j-1),1);//,add(get(i,j-1),get(i,j),1);//左 76 if(map[i][j+1]!='#')add(get(i,j),get(i,j+1),1);//,add(get(i,j+1),get(i,j),1);//右 77 //上 78 { 79 add(get(i,j),get(un[i][j],j),i-up[i][j]+1);//下 80 add(get(i,j),get(i,le[i][j]),i-up[i][j]+1);//左 81 add(get(i,j),get(i,re[i][j]),i-up[i][j]+1);//右 82 } 83 //下 84 { 85 add(get(i,j),get(up[i][j],j),un[i][j]-i+1);//上 86 add(get(i,j),get(i,le[i][j]),un[i][j]-i+1);//左 87 add(get(i,j),get(i,re[i][j]),un[i][j]-i+1);//右 88 } 89 //左 90 { 91 add(get(i,j),get(up[i][j],j),j-le[i][j]+1);//上 92 add(get(i,j),get(un[i][j],j),j-le[i][j]+1);//下 93 add(get(i,j),get(i,re[i][j]),j-le[i][j]+1);//右 94 } 95 //右 96 { 97 add(get(i,j),get(up[i][j],j),re[i][j]-j+1);//上 98 add(get(i,j),get(un[i][j],j),re[i][j]-j+1);//下 99 add(get(i,j),get(i,le[i][j]),re[i][j]-j+1);//左 100 } 101 } 102 dist(get(cx,cy)); 103 printf("%d\n",dis[get(fx,fy)]); 104 } 105 inline void add(int u,int v,int w) 106 { 107 if(u==v)return; 108 ++num_e; 109 u(num_e)=u; 110 v(num_e)=v; 111 w(num_e)=w; 112 n(num_e)=f(u); 113 f(u)=num_e; 114 }
波澜前,面不惊。