红衣男孩(bfs)
去年选拔赛的题了,现在才解决掉-_-||
以下都是别人的代码。。。
方法一:
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 }