「题解」:走格子
问题: 走格子
时间限制: 1 Sec 内存限制: 256 MB
题面
题面谢绝公开
题解
嗯,长见识了。原来网格图也可以建建边跑最短路。
考试的时候一直在想:怎么dfs的同时记录可以从哪个墙到哪个格子。
最后想出来一种美妙方案,传上十一二个参数应该就行了吧,然后果断放弃。
最后发现,只需要bfs预处理上几个数组就完美解决了……最后建边跑堆优化dijkstra就可以。
之前一直对堆优化的迪杰不感冒,觉得跟不加堆优化差不到哪里去。
然而……
普通dijkstra
堆优化dijkstra
嗯中间还改了一点点小错误但是9420和666差的有点远了吧喂!
#include<iostream> #include<cstdio> #include<cstring> #include<queue> #include<stack> #include<cmath> #include<algorithm> #define int long long #define rint register int using namespace std; int n,m,st,en,to_w[503][503],dist[503*503]; int l_w[503][503],r_w[503][503],u_w[503][503],d_w[503][503]; char str[503]; bool v[503*503],map[503][503]; struct node{int x,y;}; struct node2{int u,v,w,nxt;}edge[503*503*64]; int tot,first[503*503]; queue <node> q; priority_queue<node> QAQ; bool operator < (node a,node b){return a.y>b.y;} inline void add(int uu,int vv,int ww) { ++tot;edge[tot].u=uu;edge[tot].v=vv; edge[tot].w=ww;edge[tot].nxt=first[uu]; first[uu]=tot; } inline void bfs(){ while(q.size()){ rint x=q.front().x,y=q.front().y;q.pop(); if(map[x+1][y]&&(!to_w[x+1][y])){to_w[x+1][y]=to_w[x][y]+1;q.push((node){x+1,y});} if(map[x][y+1]&&(!to_w[x][y+1])){to_w[x][y+1]=to_w[x][y]+1;q.push((node){x,y+1});} if(map[x-1][y]&&(!to_w[x-1][y])){to_w[x-1][y]=to_w[x][y]+1;q.push((node){x-1,y});} if(map[x][y-1]&&(!to_w[x][y-1])){to_w[x][y-1]=to_w[x][y]+1;q.push((node){x,y-1});} } } inline void dij() { for(rint i=1;i<=n*m;i++) dist[i]=0x7fffffff; dist[st]=0; QAQ.push((node){st,dist[st]}); while(!QAQ.empty()) { int x=QAQ.top().x,y=QAQ.top().y; QAQ.pop(); if(y>dist[x]) continue; for(rint i=first[x];i;i=edge[i].nxt) { int to=edge[i].v,w=edge[i].w; if(dist[to]>dist[x]+w) { dist[to]=dist[x]+w; QAQ.push((node){to,dist[to]}); } } } } signed main() { scanf("%lld %lld",&n,&m); for(rint i=1;i<=n;++i) { scanf("%s",str+1); for(rint j=1;j<=m;++j) { if(str[j]=='#')map[i][j]=0,q.push((node){i,j}); if(str[j]=='C')st=(i-1)*m+j,map[i][j]=1; if(str[j]=='F')en=(i-1)*m+j,map[i][j]=1; if(str[j]=='.')map[i][j]=1; } } bfs(); for(rint i=1;i<=n;++i) for(rint j=1;j<=m;++j) if(map[i][j]) { if(!map[i][j-1])l_w[i][j]=(i-1)*m+j; else l_w[i][j]=l_w[i][j-1]; if(!map[i-1][j])u_w[i][j]=(i-1)*m+j; else u_w[i][j]=u_w[i-1][j]; } for(rint i=n;i>=1;--i) for(rint j=m;j>=1;--j) if(map[i][j]) { if(!map[i][j+1])r_w[i][j]=(i-1)*m+j; else r_w[i][j]=r_w[i][j+1]; if(!map[i+1][j])d_w[i][j]=(i-1)*m+j; else d_w[i][j]=d_w[i+1][j]; } for(rint i=1;i<=n;i++) for(rint j=1;j<=m;j++) if(map[i][j]) { int pos=(i-1)*m+j; if(map[i][j+1])add(pos,pos+1,1),add(pos+1,pos,1); if(map[i+1][j])add(pos,i*m+j,1),add(i*m+j,pos,1); if(l_w[i][j]!=pos)add(pos,l_w[i][j],to_w[i][j]); if(r_w[i][j]!=pos)add(pos,r_w[i][j],to_w[i][j]); if(u_w[i][j]!=pos)add(pos,u_w[i][j],to_w[i][j]); if(d_w[i][j]!=pos)add(pos,d_w[i][j],to_w[i][j]); } dij(); if(dist[en]>=0x7fffffff){cout<<"no"<<endl;return 0;} printf("%lld\n",dist[en]); return 0; }