分析:我们可以预处理出从'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;
}

画个豌豆射手:(以后每天画几个像素画,挂博客上)