题目描述
输入描述
输出描述
题目说明
输入样例1
5 7
000E0T3
T0TT0T0
010T0T0
2T0T0T0
0T0S000
输出样例1
3
输入样例2
1 4
SE23
输出样例2
2
题目大意: 在一片森林内存在你和其他竞争对手,你的目标是走到该森林的出口,但你的路线在其他竞争对手眼中是已知的(明牌! ),而其他竞争对手的目标是在路上偶遇你并和你打一架(不消耗时间),且每当你行动一格时,其他竞争对手也会行动一格,并且他们都很聪明不会选择绕路。求当你达到出口时所需要的最少的打架次数(即选中的某一路线上最少会遇到的其他竞争对手)。
标准阅读理解题,即使把原题生翻成中文后也很难直接看懂大意,因此不妨手模一下:
此处假设 A 为自己,B 为终点,在 A 到 B 的某一条线路上存在点 D,D 点为初始位置为 E 的敌人最早在该条线路上能与我们会合的位置。不难发现,在 D 点会合后敌人 E 完全可以与我们一起走完剩下的 DB 路段,而对于路程 DB + ED ,很显然可以得出该路程一定大于等于敌人直接从 E 走到终点 B 的距离 EB。因此对于能够在路中间的某点 D 上与我们会合的敌人,他也一定能够在终点 B 处等着我们 / 同时到达。由此可将本题转化为求当你到达终点时,同时或更早到达出口的人数。
由此本题可考虑 bfs 的思想,即从终点开始进行 bfs 搜索并标记每个方格到终点的最短路距离,并统计小于或等于自己到达终点的最短路距离的方格上的敌人数量。
参考代码
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#define x first
#define y second
using namespace std;
typedef pair<int, int> PII;
const int N = 1010;
int n, m;
char g[N][N];
int dx[4] = {
-1, 0, 1, 0}, dy[4] = {
0, 1, 0, -1};
int dist[N][N];
int bfs(){
memset(dist, 0x3f, sizeof dist);
int sx, sy;
for (int i = 0; i < n; i ++ )
for (int j = 0; j < m; j ++ )
if (g[i][j] == 'E')
sx = i, sy = j;
queue<PII> q;
q.push({
sx, sy});
dist[sx][sy] = 0;
while (q.size()){
auto t = q.front();
q.pop();
for (int i = 0; i < 4; i ++ ){
int x = t.x + dx[i], y = t.y + dy[i];
if (x >= 0 && x < n && y >= 0 && y < m && g[x][y] != 'T')
if (dist[x][y] > dist[t.x][t.y] + 1){
dist[x][y] = dist[t.x][t.y] + 1;
q.push({
x, y});
}
}
}
for (int i = 0; i < n; i ++ )
for (int j = 0; j < m; j ++ )
if (g[i][j] == 'S')
return dist[i][j];
return -1;
}
int main(){
scanf("%d%d", &n, &m);
for (int i = 0; i < n; i ++ ) scanf("%s", g[i]);
int t = bfs();
int res = 0;
for (int i = 0; i < n; i ++ )
for (int j = 0; j < m; j ++ )
if (g[i][j] > '0' && g[i][j] <= '9' && dist[i][j] <= t)
res += g[i][j] - '0';
printf("%d\n", res);
return 0;
}