题意是给一个n*m的地图,@表示起点,告诉你一些宝藏的坐标,求获得这些宝藏的最小步数。
题目里没有坑的数据,也就是不用考虑:
1.起点有宝藏
2.陷阱有宝藏
3.某个点有多个宝藏。
直接BFS就行了。
#include <iostream>
#include <cmath>
#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;
#define pi acos (-1)
#define maxn 111
#define move Move
char mp[maxn][maxn];
bool vis[maxn][maxn][1<<4];
int n, m;
int x, y;
int t, baozang[maxn][maxn];
const int move[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
struct node {
int x, y, step, k;
bool operator < (const node &a) const {
return step > a.step;
}
};
bool legal (int x, int y, int step, int k) {
if (x < 0 || y < 0 || x >= m || y >= n)
return 0;
else if (mp[x][y] == '#')
return 0;
else if (vis[x][y][k])
return 0;
else
return 1;
}
int bfs () {
priority_queue <node> gg;
while (!gg.empty ())
gg.pop ();
node from = {x, y, 0, 0};
gg.push (from);
vis[from.x][from.y][from.k] = 1;
while (!gg.empty ()) {
node from = gg.top (); gg.pop ();
node next;
if (from.k == (1<<t)-1)
return from.step;
for (int i = 0; i < 4; i++) {
next.x = from.x+move[i][0];
next.y = from.y+move[i][1];
if (!legal (next.x, next.y, from.step+1, from.k))
continue;
next.step = from.step+1;
next.k = from.k;
if (baozang[next.x][next.y]) {
if ((next.k&(1<<(baozang[next.x][next.y]-1))) == 0)
next.k = from.k+(1<<(baozang[next.x][next.y]-1));
}
gg.push (next);
vis[next.x][next.y][next.k] = 1;
}
}
return -1;
}
int main () {
//freopen ("data.txt", "r", stdin);
while (scanf ("%d%d", &m, &n) == 2 && m+n) {
for (int i = 0; i < m; i++) {
scanf ("%s", mp[i]);
for (int j = 0; j < n; j++)
if (mp[i][j] == '@')
x = i, y = j;
}
memset (baozang, 0, sizeof baozang);
memset (vis, 0, sizeof vis);
scanf ("%d", &t); int u, v;
for (int i = 1; i <= t; i++) {
scanf ("%d%d", &u, &v);
baozang[u-1][v-1] = i;
}
printf ("%d\n", bfs ());
}
return 0;
}