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 }

 

posted @ 2017-10-18 17:32  Leohh  阅读(309)  评论(0编辑  收藏  举报