• BZOJ 1656 [Usaco2006 Jan] The Grove 树木:bfs【射线法】


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

    题意:

      给你一个n*m的地图,'.'表示空地,'X'表示树林,'*'表示起点。

      所有'X'为一个连通块。

      对于每一个点,你可以向周围八个方向走,均算作一步。

      让你找出一条路径,能够将所有'X'包围。

      问你路径最短为多少。

    题解:

      bfs + 射线法。

      找出最上面(x坐标最小)的一个'X',并向上方作一条射线,标记为'#'。

      从起点开始bfs,并且不能穿过射线(即'#'不能到达)。

      最后枚举射线上的每一个点,令lef为左边能够一步到达当前点的最短路径,rig同理。

      所以ans = min (lef + rig + 2)

    AC Code:

      1 #include <iostream>
      2 #include <stdio.h>
      3 #include <string.h>
      4 #include <queue>
      5 #define MAX_N 55
      6 #define INF 1000000000
      7 
      8 using namespace std;
      9 
     10 const int dx[]={-1,1,0,0,-1,-1,1,1};
     11 const int dy[]={0,0,-1,1,-1,1,-1,1};
     12 
     13 struct Coor
     14 {
     15     int x;
     16     int y;
     17     Coor(int _x,int _y)
     18     {
     19         x=_x;
     20         y=_y;
     21     }
     22     Coor(){}
     23 };
     24 
     25 int n,m;
     26 int ans=INF;
     27 int dis[MAX_N][MAX_N];
     28 bool vis[MAX_N][MAX_N];
     29 char c[MAX_N][MAX_N];
     30 Coor start;
     31 Coor tp;
     32 queue<Coor> q;
     33 
     34 void read()
     35 {
     36     cin>>n>>m;
     37     for(int i=1;i<=n;i++)
     38     {
     39         for(int j=1;j<=m;j++)
     40         {
     41             cin>>c[i][j];
     42             if(c[i][j]=='*') start=Coor(i,j);
     43         }
     44     }
     45 }
     46 
     47 void find_line()
     48 {
     49     tp=Coor(INF,INF);
     50     for(int i=1;i<=n;i++)
     51     {
     52         for(int j=1;j<=m;j++)
     53         {
     54             if(c[i][j]=='X' && i<tp.x) tp=Coor(i,j);
     55         }
     56     }
     57     for(int i=tp.x-1;i>0;i--)
     58     {
     59         c[i][tp.y]='#';
     60     }
     61 }
     62 
     63 Coor get_front()
     64 {
     65     Coor now=q.front();
     66     q.pop();
     67     vis[now.x][now.y]=false;
     68     return now;
     69 }
     70 
     71 void insert(Coor now)
     72 {
     73     if(vis[now.x][now.y]) return;
     74     q.push(now);
     75     vis[now.x][now.y]=true;
     76 }
     77 
     78 inline bool is_legal(int x,int y)
     79 {
     80     return x>0 && x<=n && y>0 && y<=m && c[x][y]!='X' && c[x][y]!='#';
     81 }
     82 
     83 void bfs()
     84 {
     85     memset(dis,0x3f,sizeof(dis));
     86     memset(vis,false,sizeof(vis));
     87     insert(start);
     88     dis[start.x][start.y]=0;
     89     while(!q.empty())
     90     {
     91         Coor now=get_front();
     92         int x=now.x;
     93         int y=now.y;
     94         for(int i=0;i<8;i++)
     95         {
     96             int nx=x+dx[i];
     97             int ny=y+dy[i];
     98             if(is_legal(nx,ny) && dis[nx][ny]>dis[x][y]+1)
     99             {
    100                 dis[nx][ny]=dis[x][y]+1;
    101                 insert(Coor(nx,ny));
    102             }
    103         }
    104     }
    105 }
    106 
    107 void solve()
    108 {
    109     find_line();
    110     bfs();
    111     for(int i=tp.x-1;i>0;i--)
    112     {
    113         int x=i;
    114         int y=tp.y;
    115         int lef=min(dis[x][y-1],min(dis[x-1][y-1],dis[x+1][y-1]));
    116         int rig=min(dis[x][y+1],min(dis[x-1][y+1],dis[x+1][y+1]));
    117         ans=min(ans,lef+rig+2);
    118     }
    119 }
    120 
    121 void print()
    122 {
    123     cout<<ans<<endl;
    124 }
    125 
    126 int main()
    127 {
    128     read();
    129     solve();
    130     print();
    131 }
  • 相关阅读:
    Java 8特性
    11成最多体积的容器
    MySQL数据库理解
    java范型
    ArrayList源码分析
    1.面试题
    jvm简单了解
    121. 买卖股票的最佳时机
    有效的括号
    java如何判断一个字符串中某个字符有几个
  • 原文地址:https://www.cnblogs.com/Leohh/p/7687868.html
Copyright © 2020-2023  润新知