poj 1729 Jack and Jill (搜索,bfs)

原题网址:http://bailian.openjudge.cn/practice/1729

思路:

  方法1: 用点对表示两个人的状态,放在队列中(队列也可以用优先队列),当到达一个点对的路径上的最近距离大于先前求得的最近距离则进行更新。

注意:可能两人的最近距离是0,在更新的时候要注意。

      方法2: achievalbe(d2) 表示两人在最小距离平方>= d2的情况下是否能够到学校. 用距离的平方刚好能够用二分来确定两人能够到学校的路线的最远的距离.见代码三.

详细代码:

普通队列:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <queue>
 4 #include <algorithm>
 5 #include <cmath>
 6 #include <stack>
 7 using namespace std;
 8 
 9 class PointPair{
10 public:
11     int r[2],c[2];
12     PointPair(int r1=0, int c1=0, int r2=0, int c2=0){
13         r[0]=r1, r[1]=r2;
14         c[0]=c1, c[1]=c2;
15     }
16 }home,tp;
17 int dis(int r1, int c1, int r2, int c2){
18     return (r1-r2)*(r1-r2)+(c1-c2)*(c1-c2);
19 }
20 int dis(PointPair &a){
21     return dis(a.r[0], a.c[0], a.r[1], a.c[1]);
22 }
23 
24 queue<PointPair> que;
25 int n, dp[30][30][30][30][3], dx[5]={-1,1,0,0,0},dy[5]={0,0,-1,1,0},
26     hr[2],hc[2],sr[2],sc[2];
27 char mp[40][40],dir[10]="NSWE";//
28 
29 void solve(){
30     printf("%.2f\n", sqrt(dp[sr[0]][sc[0]][sr[1]][sc[1]][0]));
31     int d1 = dp[sr[0]][sc[0]][sr[1]][sc[1]][1], d2 = dp[sr[0]][sc[0]][sr[1]][sc[1]][2], r1 = sr[0], c1=sc[0], r2=sr[1], c2=sc[1];
32     stack<int> stk[2];
33     while(d1!=-1 && d2 !=-1){
34         stk[0].push(d1), stk[1].push(d2);
35         r1 -= dx[d1], c1 -= dy[d1],
36         r2 -= dx[d2], c2 -= dy[d2];
37         d1 = dp[r1][c1][r2][c2][1], d2 = dp[r1][c1][r2][c2][2];
38     }
39     for(int i=0; i<2; ++i){
40         while(!stk[i].empty() && stk[i].top()!=4){
41             printf("%c", dir[stk[i].top()]);
42             stk[i].pop();
43         }
44         printf("\n");
45     }
46     printf("\n");
47 }
48 
49 int main(){
50     while(scanf("%d", &n), n){
51         memset(dp, -1, sizeof(dp));
52         for(int i=0; i<n; ++i){
53             scanf("%s", mp[i]);
54             for(int j=0; j<n; ++j){
55                 if(mp[i][j]=='H')
56                     hr[0]=i, hc[0]=j;
57                 else if(mp[i][j]=='h')
58                     hr[1]=i, hc[1]=j;
59                 else if(mp[i][j]=='S')
60                     sr[0]=i, sc[0]=j;
61                 else if(mp[i][j]=='s')
62                     sr[1]=i,sc[1]=j;
63             }
64         }
65         home = PointPair(hr[0], hc[0], hr[1], hc[1]);
66         dp[hr[0]][hc[0]][hr[1]][hc[1]][0] = dis(home);
67         que.push(home);
68         while(!que.empty()){
69             tp = que.front(); que.pop();
70             for(int i=0; i<4; ++i){
71                 for(int j=0; j<4; ++j){
72                     int r1 = tp.r[0]+dx[i], c1 = tp.c[0]+dy[i],
73                         r2 = tp.r[1]+dx[j], c2 = tp.c[1]+dy[j],
74                         d1 = i, d2 = j;
75                     if(r1<0 || c1<0 || r1==n || c1==n || 
76                         r2<0 || c2<0 || r2==n || c2==n ||
77                         mp[r1][c1]=='*' || mp[r2][c2]=='*' ||
78                         mp[r1][c1]=='s' || mp[r1][c1]=='h'||
79                         mp[r2][c2]=='S' || mp[r2][c2]=='H') 
80                         continue;
81                     // 两人全在school的状态不会出现在队列中
82                     if(mp[tp.r[0]][tp.c[0]]=='S')
83                         r1=tp.r[0], c1=tp.c[0], d1=4;
84                     else if(mp[tp.r[1]][tp.c[1]]=='s')
85                         r2=tp.r[1], c2=tp.c[1], d2=4;
86                     int d = min(dis(r1,c1,r2,c2), dp[tp.r[0]][tp.c[0]][tp.r[1]][tp.c[1]][0]);
87                     if(d <= dp[r1][c1][r2][c2][0]) continue;// 可添加最优性剪枝
88                     dp[r1][c1][r2][c2][0] = d;
89                     dp[r1][c1][r2][c2][1] = d1;
90                     dp[r1][c1][r2][c2][2] = d2;
91                     if(mp[r1][c1]=='S' && mp[r2][c2]=='s') continue;
92                     que.push(PointPair(r1,c1,r2,c2));
93                 }
94             }
95         }
96         solve();
97     }
98     return 0;
99 }

 

 

优先队列:

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <queue>
  4 #include <algorithm>
  5 #include <cmath>
  6 #include <stack>
  7 using namespace std;
  8 
  9 int dis(int r1, int c1, int r2, int c2){
 10     return (r1-r2)*(r1-r2)+(c1-c2)*(c1-c2);
 11 }
 12 class PointPair{
 13 public:
 14     int r[2],c[2];
 15     PointPair(int r1=0, int c1=0, int r2=0, int c2=0){
 16         r[0]=r1, r[1]=r2;
 17         c[0]=c1, c[1]=c2;
 18     }
 19     int operator<(const PointPair &b) const{
 20         return dis(r[0],c[0],r[1],c[1])<dis(b.r[0],b.c[0],b.r[1],b.c[1]);
 21     }
 22 }home,tp;
 23 int dis(PointPair &a){
 24     return dis(a.r[0], a.c[0], a.r[1], a.c[1]);
 25 }
 26 
 27 priority_queue<PointPair> que;
 28 int n, dp[30][30][30][30][3], dx[5]={-1,1,0,0,0},dy[5]={0,0,-1,1,0},
 29     hr[2],hc[2],sr[2],sc[2], rev[5]={1,0,3,2,4};
 30 char mp[40][40],dir[10]="NSWE";//
 31 
 32 void solve(){
 33     printf("%.2f\n", sqrt(dp[sr[0]][sc[0]][sr[1]][sc[1]][0]));
 34     int d1 = dp[sr[0]][sc[0]][sr[1]][sc[1]][1], d2 = dp[sr[0]][sc[0]][sr[1]][sc[1]][2], r1 = sr[0], c1=sc[0], r2=sr[1], c2=sc[1];
 35     stack<int> stk[2];
 36     while(d1!=-1 && d2 !=-1){
 37         stk[0].push(d1), stk[1].push(d2);
 38         r1 += dx[rev[d1]], c1 += dy[rev[d1]],
 39         r2 += dx[rev[d2]], c2 += dy[rev[d2]];
 40         d1 = dp[r1][c1][r2][c2][1], d2 = dp[r1][c1][r2][c2][2];
 41     }
 42     for(int i=0; i<2; ++i){
 43         while(!stk[i].empty() && stk[i].top()!=4){
 44             printf("%c", dir[stk[i].top()]);
 45             stk[i].pop();
 46         }
 47         printf("\n");
 48     }
 49     printf("\n");
 50 }
 51 
 52 int main(){
 53     while(scanf("%d", &n), n){
 54         memset(dp, -1, sizeof(dp));
 55         for(int i=0; i<n; ++i){
 56             scanf("%s", mp[i]);
 57             for(int j=0; j<n; ++j){
 58                 if(mp[i][j]=='H')
 59                     hr[0]=i, hc[0]=j;
 60                 else if(mp[i][j]=='h')
 61                     hr[1]=i, hc[1]=j;
 62                 else if(mp[i][j]=='S')
 63                     sr[0]=i, sc[0]=j;
 64                 else if(mp[i][j]=='s')
 65                     sr[1]=i,sc[1]=j;
 66             }
 67         }
 68         home = PointPair(hr[0], hc[0], hr[1], hc[1]);
 69         dp[hr[0]][hc[0]][hr[1]][hc[1]][0] = dis(home);
 70         que.push(home);
 71         while(!que.empty()){
 72             // tp = que.front(); que.pop();
 73             tp = que.top(); que.pop();
 74             for(int i=0; i<4; ++i){
 75                 for(int j=0; j<4; ++j){
 76                     int r1 = tp.r[0]+dx[i], c1 = tp.c[0]+dy[i],
 77                         r2 = tp.r[1]+dx[j], c2 = tp.c[1]+dy[j],
 78                         d1 = i, d2 = j;
 79                     if(r1<0 || c1<0 || r1==n || c1==n || 
 80                         r2<0 || c2<0 || r2==n || c2==n ||
 81                         mp[r1][c1]=='*' || mp[r2][c2]=='*' ||
 82                         mp[r1][c1]=='s' || mp[r1][c1]=='h'||
 83                         mp[r2][c2]=='S' || mp[r2][c2]=='H') 
 84                         continue;
 85                     // 两人全在school的状态不会出现在队列中
 86                     if(mp[tp.r[0]][tp.c[0]]=='S')
 87                         r1=tp.r[0], c1=tp.c[0], d1=4;
 88                     else if(mp[tp.r[1]][tp.c[1]]=='s')
 89                         r2=tp.r[1], c2=tp.c[1], d2=4;
 90                     int d = min(dis(r1,c1,r2,c2), dp[tp.r[0]][tp.c[0]][tp.r[1]][tp.c[1]][0]);
 91                     if(d <= dp[r1][c1][r2][c2][0]) continue;// 可添加最优性剪枝
 92                     dp[r1][c1][r2][c2][0] = d;
 93                     dp[r1][c1][r2][c2][1] = d1;
 94                     dp[r1][c1][r2][c2][2] = d2;
 95                     if(mp[r1][c1]=='S' && mp[r2][c2]=='s') continue;
 96                     que.push(PointPair(r1,c1,r2,c2));
 97                 }
 98             }
 99         }
100         solve();
101     }
102     return 0;
103 }
View Code

 

方法二:

  1 #include <cstdio>
  2 #include <cmath>
  3 #include <queue>
  4 #include <stack>
  5 #include <cstring>
  6 #include <algorithm>
  7 
  8 using namespace std;
  9 
 10 char mp[40][40], dir[] = "NSWE", rdir[] = "SNEW";
 11 int n, dp[30][30][30][30], mk[30][30][30][30];
 12 int dy[4] = {0, 0, -1, 1}, dx[4] = {-1, 1, 0, 0};
 13 
 14 class Point{
 15 public:
 16     int x, y;
 17     Point(int _x=0, int _y=0): x(_x), y(_y) {}
 18 }home[2], sch[2];
 19 
 20 
 21 int dis2(Point a, Point b){
 22     return (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y);
 23 }
 24 
 25 
 26 bool not_in_map(int x){
 27     return x < 0 || x >= n;
 28 }
 29 
 30 
 31 int achievable(int d, int print=0){
 32     queue<int> que;
 33 
 34     memset(dp, 0x8, sizeof(dp));
 35     
 36     if(min(dis2(home[0], home[1]), dis2(sch[0], sch[1])) < d) 
 37         return 0;
 38     dp[home[0].x][home[0].y][home[1].x][home[1].y] = 0;
 39     que.push(home[0].x); que.push(home[0].y); que.push(home[1].x); que.push(home[1].y);
 40 
 41     while(!que.empty()){
 42         int x0, y0, x1, y1;
 43         x0 = que.front(); que.pop(); y0 = que.front(); que.pop(); 
 44         x1 = que.front(); que.pop(); y1 = que.front(); que.pop(); 
 45         for(int i=0; i<4; ++i){
 46             for(int j=0; j<4; ++j){
 47                 int tx0 = x0, ty0 = y0, tx1 = x1, ty1 = y1;
 48                 if(!(x0 == sch[0].x && y0 == sch[0].y))
 49                     tx0 += dx[i], ty0 += dy[i];
 50                 if(!(x1 == sch[1].x && y1 == sch[1].y))
 51                     tx1 += dx[j], ty1 += dy[j];
 52                 if(not_in_map(tx0) || not_in_map(ty0) || not_in_map(tx1) || not_in_map(ty1))
 53                     continue;
 54                 if(mp[tx0][ty0] == '*' || mp[tx0][ty0] == 'S' || mp[tx0][ty0] == 'H')
 55                     continue;
 56                 if(mp[tx1][ty1] == '*' || mp[tx1][ty1] == 's' || mp[tx1][ty1] == 'h')
 57                     continue;
 58                 if(dis2(Point(tx0, ty0), Point(tx1, ty1)) < d)
 59                     continue;
 60                 if(dp[tx0][ty0][tx1][ty1] > dp[x0][y0][x1][y1] + 1){
 61                     dp[tx0][ty0][tx1][ty1] = dp[x0][y0][x1][y1] + 1;
 62                     que.push(tx0); que.push(ty0); que.push(tx1); que.push(ty1);
 63                     if(mp[tx0][ty0] == 's' && mp[tx1][ty1] == 'S')
 64                         return 1;
 65                 }
 66             }
 67         }
 68     }
 69     
 70     return 0;
 71 }
 72 
 73 
 74 void print_path(){
 75     stack<char> p[2];
 76     int x0 = sch[0].x, y0 = sch[0].y, x1 = sch[1].x, y1 = sch[1].y;
 77 
 78     while(!(mp[x0][y0] == 'h' && mp[x1][y1] == 'H')){
 79         for(int i=0; i<5; ++i){
 80             for(int j=0; j<5; ++j){
 81                 int tx0 = x0, ty0 = y0, tx1 = x1, ty1 = y1;
 82                 if(i < 4 || mp[x0][y0] != 's')
 83                     tx0 += dx[i], ty0 += dy[i];
 84                 if(j < 4 || mp[x1][y1] != 'S')
 85                     tx1 += dx[j], ty1 += dy[j];
 86                 if(i == 4 && j == 4) 
 87                     continue;
 88                 if(not_in_map(tx0) || not_in_map(ty0) || not_in_map(tx1) || not_in_map(ty1))
 89                     continue;
 90                 if(!(dp[tx0][ty0][tx1][ty1] + 1 == dp[x0][y0][x1][y1]))
 91                     continue;
 92                 if(mp[tx0][ty0] != 's')
 93                     p[0].push(rdir[i]);
 94                 if(mp[tx1][ty1] != 'S')
 95                     p[1].push(rdir[j]);
 96                 if(mp[tx0][ty0] == 'h' && mp[tx1][ty1] == 'H'){
 97                     for(int k=0; k<2; ++k){
 98                         while(!p[1-k].empty()){
 99                             printf("%c", p[1-k].top()); p[1-k].pop();
100                         }
101                         printf("\n");
102                     }
103                     return;
104                 }
105                 x0 = tx0, y0 = ty0, x1 = tx1, y1 = ty1;
106                 goto out;
107             }
108         }
109         out: {}
110     }
111 }
112 
113 
114 int main(){
115     freopen("input.txt", "r", stdin);
116 
117     while(scanf("%d", &n) && n){
118         for(int i=0; i<n; ++i){
119             scanf("%s", mp[i]);
120             for(int j=0; j<n; ++j){
121                 switch(mp[i][j]){
122                     case 'h': home[0] = Point(i, j); break;
123                     case 'H': home[1] = Point(i, j); break;
124                     case 's': sch[0] = Point(i, j); break;
125                     case 'S': sch[1] = Point(i, j); break;
126                     default: break;
127                 }
128             }
129         }
130 
131         int mx = min(dis2(home[0], home[1]), dis2(sch[0], sch[1])) + 1, mn = 0;
132         while(mx > mn){
133             int d = (mx + mn) >> 1;
134             if(achievable(d))
135                 mn = d + 1;
136             else 
137                 mx = d;
138         }
139         achievable(mx - 1);
140         printf("%.2f\n", sqrt(mx - 1));
141         print_path();
142     }
143 
144     return 0;
145 }
View Code

 

posted @ 2016-08-19 23:22  Keep_Going  阅读(855)  评论(0编辑  收藏  举报