• 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
    ",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 }
    View Code
  • 相关阅读:
    初识Ubuntu 18.04(更换系统头像,截图,sy)
    HDU
    HDU
    进度1
    开课博客
    返回一个整数数组中最大子数组的和
    开学第一节课测试感受
    网页记账本开发四(基本完成)
    网页记账本开发三
    网页记账本开发二
  • 原文地址:https://www.cnblogs.com/Al-Ca/p/11318850.html
Copyright © 2020-2023  润新知