红衣男孩(bfs)

题目连接:https://scut.online/p/10

去年选拔赛的题了,现在才解决掉-_-||

以下都是别人的代码。。。

方法一:

 1 #include<iostream>
 2 #include<string>
 3 #include<algorithm>
 4 #include<math.h>
 5 #include<string.h>
 6 #include<queue>
 7 #include<stdio.h>
 8 using namespace std;
 9 int n, m;
10 int ex, ey;
11 int bx, by;
12 int mapp[1005][1005];
13 int step[1005][1005];
14 int money[1005][1005];
15 int dix[4] = { 1, -1, 0, 0 };
16 int diy[4] = { 0, 0, 1, -1 };
17 class point{
18 public:
19     int money;
20     int step;
21     int x, y;
22     point(int ax, int ay, int mon,int st){
23         money = mon;
24         x = ax;
25         y = ay;
26         step = st;
27     }
28 };
29 queue<point> line;
30 
31 int solve(){
32     int ans_step = 0x3f3f3f3f;
33     int ans_money = -1;
34     while (!line.empty()){
35         point cnt = line.front();
36         line.pop();
37         if (cnt.step > ans_step){ break; }
38         if (cnt.x == ex&&cnt.y == ey){
39             if (cnt.step < ans_step || (cnt.step == ans_step&&cnt.money>ans_money)){
40                 ans_money = cnt.money; ans_step = cnt.step;
41             }
42             continue;
43         }
44         if (step[cnt.x][cnt.y] == 0 ||cnt.step < step[cnt.x][cnt.y] ||
45             (cnt.step == step[cnt.x][cnt.y] && cnt.money>money[cnt.x][cnt.y]))
46         { 
47             step[cnt.x][cnt.y] = cnt.step; 
48             money[cnt.x][cnt.y] = cnt.money; 
49         }
50         else if (cnt.step > step[cnt.x][cnt.y] || 
51            cnt.step == step[cnt.x][cnt.y] && cnt.money<money[cnt.x][cnt.y])
52             { continue; }
53         for (int i = 0; i < 4; i++){
54             point newp(cnt.x + dix[i], cnt.y + diy[i], cnt.money + mapp[cnt.x + dix[i]][cnt.y + diy[i]], cnt.step + 1);
55             if (newp.x>0 && newp.x <= n&&newp.y>0 && newp.y <= m&&mapp[newp.x][newp.y] != -1)
56             {
57                 if (step[newp.x][newp.y] == 0 || newp.step < step[newp.x][newp.y] ||
58                     (newp.step == step[newp.x][newp.y] && newp.money>money[newp.x][newp.y]))
59                 {
60                     line.push(newp);
61                     step[newp.x][newp.y] = newp.step; money[newp.x][newp.y] = newp.money; 
62                 }       
63             }
64         }
65     }
66     while (!line.empty()){ line.pop(); }
67     return ans_money;
68 }
69 
70 int main(){
71     int t;
72     scanf("%d", &t);
73     while (t--){
74         memset(step, 0, sizeof(step));
75         memset(money, 0, sizeof(money));
76         scanf("%d%d", &n, &m);
77         scanf("%d%d%d%d", &bx, &by,&ex,&ey);
78         for (int i = 1; i <= n; i++)
79             for (int j = 1; j <= m; j++)
80                 scanf("%d", &mapp[i][j]);
81                     
82             point beg(bx, by, mapp[bx][by], 1);
83             line.push(beg);
84             step[bx][by] = 1;
85             printf("%d\n", solve());
86     }
87     return 0;
88 }

 

 

方法二:

这个题目很容易让人想到广搜,但其实只要在保证路程最短的情况下就可以随便搜了。
这里提供的解法其实很简单,用两个队列来维护就可以了,一个队列表示第i步走到的格子,另一个队列则从这个队列中得到第i+1步走到的格子。用一个新的地图来存每一个格子中的当前最优值即可。注意对格子进行判重,一个格子进队列多次可能会导致超时。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <set>
 5 #include <algorithm>
 6 using namespace std;
 7 
 8 const int MAX_N = 1000;
 9 const int MAX_M = 1000;
10 
11 const int d[4][2] = {{-1,0},{1,0},{0,-1},{0,1}};
12 
13 int N, M;
14 int Sx, Sy, Tx, Ty;
15 int mp[MAX_N][MAX_M];
16 int val[MAX_N][MAX_M];
17 
18 set<pair<int, int> > S[2];
19 
20 int main()
21 {
22     int TEST;
23     scanf("%d", &TEST);
24     while (TEST--)
25     {
26         scanf("%d%d", &N, &M);
27         scanf("%d%d%d%d", &Sx, &Sy, &Tx, &Ty);
28         --Sx, --Sy, --Tx, --Ty;
29         for (int i = 0; i < N; ++i)
30             for (int j = 0; j < M; ++j)
31             {
32                 scanf("%d", mp[i] + j);
33                 val[i][j] = -1;
34             }
35         
36         bool reach = false;
37         S[0].clear(), S[1].clear();
38         S[0].insert(make_pair(Sx, Sy));
39         val[Sx][Sy] = mp[Sx][Sy];
40         for (int i = 0; ; i ^= 1)
41         {
42             if (reach||S[i].empty()) break;
43             for (set<pair<int, int> >::iterator iter = S[i].begin(); iter != S[i].end(); ++iter)
44             {
45                 for (int j = 0; j < 4; ++j)
46                 {
47                     const int X = iter->first + d[j][0], Y = iter->second + d[j][1];
48                     if (X < 0 || N <= X || Y < 0 || M <= Y || mp[X][Y] < 0 || val[X][Y] >= 0) continue;
49                     S[i^1].insert(make_pair(X, Y));
50                 }
51             }
52             for (set<pair<int, int> >::iterator iter = S[i^1].begin(); iter != S[i^1].end(); ++iter)
53             {
54                 const int X = iter->first, Y = iter->second;
55                 if (X == Tx && Y == Ty) reach = true;
56                 for (int j = 0; j < 4; ++j)
57                 {
58                     if (S[i].count(make_pair(X+d[j][0], Y+d[j][1])))
59                         val[X][Y] = max(val[X][Y], val[X+d[j][0]][Y+d[j][1]] + mp[X][Y]);
60                 }
61             }
62             S[i].clear();
63         }
64         printf("%d\n", val[Tx][Ty]);
65     }
66     return 0;
67 }

 

posted @ 2017-05-03 22:47  yijiull  阅读(150)  评论(0编辑  收藏  举报