题目链接:HDU 2612
题意:
给一张地图,"Y"和"M"表示两个人的位置,"#"表示道路不通,"."表示道路可行,"@"表示KFC,求从两个人分别从各自起点出发到一家KFC的最短路径和。
分析:
一开始是想对每一家KFC分别求出两个人的路径,然后相加,取最小值,可是这样果然TLE了,部分代码如下:
int bfs(int sx,int sy,int ex,int ey)
{//(sx,sy)是人的起点坐标,(ex,ey)是KFC坐标
memset(vis, 0, sizeof(vis));
queue<Node> q;
cur.a = sx, cur.b = sy, cur.step = 0;
vis[sx][sy] = 1;
q.push(cur);
while (!q.empty())
{
cur = q.front();
q.pop();
for (int i = 0; i < 4; i++)
{
tx = cur.a + dir[i][0];
ty = cur.b+ dir[i][1];
if (!valid(tx, ty)) continue;
nextnode.a = tx, nextnode.b = ty, nextnode.step = cur.step + 1;
vis[tx][ty] = 1;
if (tx == ex&&ty == ey) return nextnode.step;
q.push(nextnode);
}
}
return -1;
}
于是改了,先对每个人到每家KFC的最短路径做预处理,然后对每家KFC两个最短路径相加,再取最小值,这下就AC了。需要特别注意的是,有的KFC可能到达不了!所以每个人需要一个vis数组用以记录这个KFC能否到达,这有两个人都能到达了,才符合!
CODE:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <cmath>
#include <cctype>
using namespace std;
const int maxn = 210;
char s[maxn], a[maxn][maxn];
int vis1[maxn][maxn],vis2[maxn][maxn];
int i, j, r, c, ans;
int dis1[maxn][maxn], dis2[maxn][maxn];
int yx, yy, mx, my, tx, ty;
int dir[4][2] = { {0,1},{1,0},{-1,0},{0,-1} };
int valid(int x, int y)
{
if (x < 0 || y < 0 || x >= r || y >= c || a[x][y] == '#') return 0;
return 1;
}
struct Node {
int a, b;
int step;
}cur, nextnode;
void bfs(int sx, int sy, int dis[210][210],int vis[210][210])
{
memset(vis, 0, sizeof(vis));
memset(dis, 0, sizeof(dis));
queue<Node> q;
cur.a = sx, cur.b = sy, cur.step = 0;
vis[sx][sy] = 1;
q.push(cur);
while (!q.empty())
{
cur = q.front();
q.pop();
for (int i = 0; i < 4; i++)
{
tx = cur.a + dir[i][0];
ty = cur.b + dir[i][1];
if (!valid(tx, ty)||vis[tx][ty]) continue;
nextnode.a = tx, nextnode.b = ty, nextnode.step = cur.step + 1;
vis[tx][ty] = 1;
if (a[tx][ty] == '@')
{
dis[tx][ty] = nextnode.step;
//printf("(%d,%d) step:%d\n", tx, ty, nextnode.step);
}
q.push(nextnode);
}
}
}
int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
#endif
while (~scanf("%d%d", &r, &c))
{
for (i = 0; i < r; i++)
{
scanf("%s", s);
for (j = 0; j < c; j++)
{
a[i][j] = s[j];
if (a[i][j] == 'Y')
{
yx = i;
yy = j;
}
else if (a[i][j] == 'M')
{
mx = i;
my = j;
}
}
}
memset(vis1, 0, sizeof(vis1));
bfs(yx, yy, dis1, vis1);
//printf("*********\n");
memset(vis2, 0, sizeof(vis2));
bfs(mx, my, dis2, vis2);
ans = 1000000000;
for (i = 0; i < r; i++)
{
for (j = 0; j < c; j++)
{
if (a[i][j] == '@'&&vis1[i][j]&&vis2[i][j])
{
ans = min(ans, dis1[i][j]+dis2[i][j]);
}
}
}
printf("%d\n", ans * 11);
}
return 0;
}