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 }