分析:我们可以预处理出从'D','E'往四个方向,能被其它格子看到的坐标。然后用一个状态数组标记走过的格子,即\(st[pos.y][pos.x][d][e]\),前两维表示走过的格子,第三维表示是否看到大明,第四维表示是否能看到二明。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
using PII = pair<int, int>;
const int N = 105;
char g[N][N];
//小明,大明,二明
PII s, e, d;
//每个点是否能看到大明、二明
bool look[N][N][2];
int dx[] = { -1, 1, 0, 0 };
int dy[] = { 0, 0, -1, 1 };
int n, m, time;
char id[2] = { 'D', 'E' };
struct Node
{
int y, x;
int step;
bool d, e;
};
bool st[N][N][2][2];
void test_look(PII pos, int type)
{
for (int i = 0; i < 4; ++i)
{
int ny = pos.first, nx = pos.second;
while (true)
{
ny += dy[i], nx += dx[i];
if (g[ny][nx] == 'X' || g[ny][nx] == id[1 - type]) break;
if (ny < 1 || ny > n || nx < 1 || nx > m) break;
look[ny][nx][type] = true;
}
}
}
int bfs()
{
memset(st, 0, sizeof st);
queue<Node> q;
Node p;
p.step = 0, p.d = false, p.e = false;
p.y = s.first, p.x = s.second;
if (look[s.first][s.second][0]) p.d = true;
if (look[s.first][s.second][1]) p.e = true;
q.push(p);
while (q.size())
{
Node p = q.front();
q.pop();
if (p.d && p.e) return p.step;
if (p.step > time) return -1;
for (int i = 0; i < 4; ++i)
{
Node now = p;
now.y += dy[i];
now.x += dx[i];
++now.step;
if (now.y < 1 || now.y > n || now.x < 1 || now.x > m) continue;
if (g[now.y][now.x] == 'X' || g[now.y][now.x] == 'E' || g[now.y][now.x] == 'D') continue;
if (look[now.y][now.x][0]) now.d = true;
if (look[now.y][now.x][1]) now.e = true;
if (st[now.y][now.x][now.d][now.e]) continue;
st[now.y][now.x][now.d][now.e] = true;
q.push(now);
}
}
return -1;
}
int main()
{
int t;
scanf("%d", &t);
int c = 0;
while (t--)
{
scanf("%d%d%d", &n, &m, &time);
for (int i = 1; i <= n; ++i) scanf("%s", *(g + i) + 1);
for (int i = 1; i <= n; ++i)
{
for (int j = 1; j <= m; ++j)
{
if (g[i][j] == 'S')
{
s = make_pair(i, j);
}
if (g[i][j] == 'D')
{
d = make_pair(i, j);
}
if (g[i][j] == 'E')
{
e = make_pair(i, j);
}
}
}
memset(look, 0, sizeof look);
test_look(d, 0);
test_look(e, 1);
int res = bfs();
printf("Case %d:\n%d\n", ++c, res);
}
return 0;
}
画个豌豆射手:(以后每天画几个像素画,挂博客上)