P2864 [USACO06JAN]树林The Grove

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 }
View Code

 

posted @ 2018-12-06 16:45  kafuuchino  阅读(338)  评论(0编辑  收藏  举报