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 }
优先队列:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }
方法二:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }