P2864 [USACO06JAN]树林The Grove
神奇的射线法+bfs
裸的bfs很难写.......
那么我们找一个最外围障碍点,向图的外边引一条虚拟射线。
蓝后bfs时经过这条射线奇数次最后又回到起点的,就是满足条件的路径
最后来个bfs+记忆化
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<queue> 5 using namespace std; 6 #define N 55 7 const int d1[8]={-1,1,0,0,-1,-1,1,1}; 8 const int d2[8]={0,0,-1,1,-1,1,-1,1}; 9 struct data{ 10 int x,y,k;//k:穿过次数 11 data(){} 12 data(int A,int B,int C): 13 x(A),y(B),k(C){} 14 }; queue <data> h; 15 int n,m,gx,gy,tx,ty,d[N][N][2]; 16 char q[N]; bool a[N][N]; 17 bool across(data f,data t){ 18 if(gx==f.x&&gy>f.y&&gx>t.x) return 1;//自下而上穿过 19 if(gx==t.x&&gy>t.y&&gx>f.x) return 1;//自上而下穿过 20 return 0; 21 } 22 int main(){ 23 memset(d,127,sizeof(d)); 24 scanf("%d%d",&n,&m); 25 for(int i=1;i<=n;++i){ 26 scanf("%s",q+1); 27 for(int j=1;j<=m;++j){ 28 if(q[j]=='X'){ 29 a[i][j]=1; 30 if(!gx) gx=i,gy=j;//找一个障碍点,最好是外围的 31 }else if(q[j]=='*'){ 32 d[tx=i][ty=j][0]=0; 33 h.push(data(i,j,0)); 34 } 35 } 36 } 37 while(!h.empty()){ 38 data u=h.front(),p; h.pop(); 39 for(int i=0;i<8;++i){ 40 p=data(u.x+d1[i],u.y+d2[i],u.k); 41 if(p.x<1||p.x>n||p.y<1||p.y>m) 42 continue; 43 if(a[p.x][p.y]) continue; 44 if(across(u,p)) p.k^=1; 45 if(d[p.x][p.y][p.k]<=d[u.x][u.y][u.k]+1) 46 continue; 47 d[p.x][p.y][p.k]=d[u.x][u.y][u.k]+1; 48 h.push(p); 49 } 50 }printf("%d",d[tx][ty][1]);//穿过奇数次回到起点的 51 return 0; 52 }