「题解」:走格子

问题: 走格子

时间限制: 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;
}
View Code

 

posted @ 2019-08-08 10:24  hzoi_Joe  阅读(336)  评论(4编辑  收藏  举报