zoukankan      html  css  js  c++  java
  • BZOJ 1632 [Usaco2007 Feb]Lilypad Pond:spfa【同时更新:经过边的数量最小】【路径数量】

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1632

    题意:

      有一个n*m的池塘。0代表水,1代表荷花,2代表岩石,3代表起点,4代表终点。

      Bessie在练芭蕾舞,她要从起点跳到终点去。

      她只能走“日”字形,并且只能跳到荷花上。

      荷花不能长在岩石上。

      问你:

        (1)至少要再添加多少个荷花,才能使Bessie可以跳到终点。

        (2)在(1)的前提下,让Bessie跳到终点的步数最小,并输出。

        (3)在(1)(2)条件下的路径条数。

    题解:

      方便起见,对于每个点(x,y)可以表示成x*m+y的形式,即平面上的点在实数上的唯一映射。

      

      第一问:

        建图。

        对于每个点,到水建一条边长为1的边,到荷花建一条边长为0的边。

        跑一边spfa,第一问就出来了。

      第二问:

        在spfa中更新dis的时候,分两种情况:

          (1)dis[dest]==-1 || dis[dest]>dis[now]+len

            此时dis被更新,相应的step[dest]一定要变成step[now]+1。

          (2)dis[dest]==dis[now]+len

            dis未被更新,但step有可能更优,step[dest] = min(step[dest], step[now]+1)

      第三问:

        在前两问都不变的情况下,才有可能 cnt[dest] += cnt[now]。

        否则cnt[dest] = cnt[now]

    AC Code:

      1 #include <iostream>
      2 #include <stdio.h>
      3 #include <string.h>
      4 #include <vector>
      5 #include <queue>
      6 #define MAX_N 35
      7 #define MAX_P 905
      8 
      9 using namespace std;
     10 
     11 const int dx[]={-2,-2,-1,-1,1,1,2,2};
     12 const int dy[]={-1,1,-2,2,-2,2,-1,1};
     13 
     14 struct Edge
     15 {
     16     int dest;
     17     int len;
     18     Edge(int _dest,int _len)
     19     {
     20         dest=_dest;
     21         len=_len;
     22     }
     23     Edge(){}
     24 };
     25 
     26 int n,m;
     27 int start,over;
     28 int dis[MAX_P];
     29 int step[MAX_P];
     30 long long cnt[MAX_P];
     31 int a[MAX_N][MAX_N];
     32 bool vis[MAX_P];
     33 vector<Edge> edge[MAX_P];
     34 queue<int> q;
     35 
     36 void read()
     37 {
     38     cin>>n>>m;
     39     for(int i=0;i<n;i++)
     40     {
     41         for(int j=0;j<m;j++)
     42         {
     43             cin>>a[i][j];
     44             if(a[i][j]==3) start=i*m+j;
     45             if(a[i][j]==4) over=i*m+j;
     46         }
     47     }
     48 }
     49 
     50 inline bool is_legal(int x,int y)
     51 {
     52     return x>=0 && x<n && y>=0 && y<m;
     53 }
     54 
     55 void build_graph()
     56 {
     57     for(int i=0;i<n;i++)
     58     {
     59         for(int j=0;j<m;j++)
     60         {
     61             for(int k=0;k<8;k++)
     62             {
     63                 int x=i+dx[k];
     64                 int y=j+dy[k];
     65                 if(is_legal(x,y) && a[x][y]!=2)
     66                 {
     67                     edge[i*m+j].push_back(Edge(x*m+y,a[x][y]==0));
     68                 }
     69             }
     70         }
     71     }
     72 }
     73 
     74 int get_front()
     75 {
     76     int now=q.front();
     77     q.pop();
     78     vis[now]=false;
     79     return now;
     80 }
     81 
     82 void insert(int now)
     83 {
     84     if(vis[now]) return;
     85     q.push(now);
     86     vis[now]=true;
     87 }
     88 
     89 void spfa(int start)
     90 {
     91     memset(dis,-1,sizeof(dis));
     92     memset(step,0x3f,sizeof(step));
     93     memset(cnt,0,sizeof(cnt));
     94     memset(vis,false,sizeof(vis));
     95     insert(start);
     96     dis[start]=0;
     97     step[start]=0;
     98     cnt[start]=1;
     99     while(!q.empty())
    100     {
    101         int now=get_front();
    102         for(int i=0;i<edge[now].size();i++)
    103         {
    104             Edge temp=edge[now][i];
    105             if(dis[temp.dest]==-1 || dis[temp.dest]>dis[now]+temp.len)
    106             {
    107                 dis[temp.dest]=dis[now]+temp.len;
    108                 step[temp.dest]=step[now]+1;
    109                 cnt[temp.dest]=cnt[now];
    110                 insert(temp.dest);
    111             }
    112             else if(dis[temp.dest]==dis[now]+temp.len)
    113             {
    114                 if(step[temp.dest]>step[now]+1)
    115                 {
    116                     step[temp.dest]=step[now]+1;
    117                     cnt[temp.dest]=cnt[now];
    118                     insert(temp.dest);
    119                 }
    120                 else if(step[temp.dest]==step[now]+1)
    121                 {
    122                     cnt[temp.dest]+=cnt[now];
    123                     insert(temp.dest);
    124                 }
    125             }
    126         }
    127     }
    128 }
    129 
    130 void solve()
    131 {
    132     build_graph();
    133     spfa(start);
    134 }
    135 
    136 void print()
    137 {
    138     cout<<dis[over]<<endl;
    139     if(dis[over]!=-1)
    140     {
    141         cout<<step[over]<<endl;
    142         cout<<cnt[over]<<endl;
    143     }
    144 }
    145 
    146 int main()
    147 {
    148     read();
    149     solve();
    150     print();
    151 }
  • 相关阅读:
    monkeyrunner1
    也来复习一下数据库的一些知识1
    Monkey原理
    总结一下app客户端的测试点
    从侧计--mongkeyScript问题
    从侧计----monkeyScript实例----开启墨迹天气并添加城市,最后关闭app
    求助:关于sql如何统计时间的问题
    虚拟机无法分配内存 virtual memory exhausted: Cannot allocate memory
    Ubuntu14.04安装libusb
    E: 软件包 ffmpeg 没有可供安装的候选者
  • 原文地址:https://www.cnblogs.com/Leohh/p/7618340.html
Copyright © 2011-2022 走看看