poj 1729 Jack and Jill (搜索,bfs)

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

思路:

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

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

详细代码:

普通队列:

 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], rev[5]={1,0,3,2,4};
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[rev[d1]], c1 += dy[rev[d1]],
36         r2 += dx[rev[d2]], c2 += dy[rev[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 }

时间: 2024-08-01 11:47:58

poj 1729 Jack and Jill (搜索,bfs)的相关文章

POJ 2329 (暴力+搜索bfs)

Nearest number - 2 Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 3943 Accepted: 1210 Description Input is the matrix A of N by N non-negative integers. A distance between two elements Aij and Apq is defined as |i ? p| + |j ? q|. Your pro

POJ 1130(一道纯水,bfs+dfs)

POJ 1130 大概题意:给出一副图,求从起点到终点 (0->ET) 必须经过的一点. 我的思路:首先DFS求出经过每点的次数,必过的一点的次数一定最高,但是就这样吗?有可能有多个必过的点,所以还要找出离ET最近的点,这里就利用BFS逐层搜索的性质求每点到ET的距离. #include<iostream> #include<cstdio> #include<string.h> #include<iomanip> #include<queue&g

[ACM] POJ 1753 Flip Game (枚举,BFS,位运算)

Flip Game Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 29921   Accepted: 12975 Description Flip game is played on a rectangular 4x4 field with two-sided pieces placed on each of its 16 squares. One side of each piece is white and the

[ACM] poj 1088 滑雪 (记忆化搜索DFS)

求n*m网格内矩形的数目[ACM] poj 1088 滑雪 (记忆化搜索DFS),布布扣,bubuko.com

POJ 3278 Catch That Cow --- 简单BFS

/* POJ 3278 Catch That Cow --- 简单BFS */ #include <cstdio> #include <queue> #include <cstring> using namespace std; const int maxn = 100005; bool visit[maxn]; int step[maxn]; int bfs(int n, int k){ if (n == k) return 0; memset(visit, 0, s

POJ 2243 || HDU 1372:Knight Moves(BFS)

Knight Moves Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 11223 Accepted: 6331 Description A friend of you is doing research on the Traveling Knight Problem (TKP) where you are to find the shortest closed tour of knight moves that visit

poj 3156 hash+记忆化搜索 期望dp

#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; int n,m; #define N 32 #define mod 10007LL #define mod2 10000007 #define inf 0x3fffffff typedef long long ll; typedef double dd; int f[N]

POJ 3278 Catch That Cow(BFS 剪枝)

题目链接:http://poj.org/problem?id=3278 这几次都是每天的第一道题都挺顺利,然后第二道题一卡一天. = =,今天的这道题7点40就出来了,不知道第二道题在下午7点能不能出来.0 0 先说说这道题目,大意是有个农夫要抓牛,已知牛的坐标,和农夫位置.而且农夫有三种移动方式,X + 1,X - 1,X * 2,问最少几步抓到牛. 开始认为很简单的,三方向的BFS就能顺利解决,然后在忘开标记的情况下直接广搜,果然TLE,在你计算出最少位置之前,牛早跑了. 然后反应过来开标记

Poj 3087 Shuffle&#39;m Up 【BFS】

Shuffle'm Up Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 6556 Accepted: 3077 Description A common pastime for poker players at a poker table is to shuffle stacks of chips. Shuffling chips is performed by starting with two stacks of pok