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

 

转载于:https://www.cnblogs.com/yyf2016/p/5789382.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值