用全排列枚举每一个种走的情况,再取最小的那个即可。
贴代码:(AC,15ms)
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int MAX = 105;
const int INF = 0x7fffff;
int n, m;
char map[MAX][MAX];
bool vis[MAX][MAX];
int Move[4][2] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}};
int step, cnt;
int sx, sy, ex, ey, ca;
struct point{
int x, y, step;
}to, tp, p[4], temp;
point bfs(point s, int flag){
memset(vis, false, sizeof(vis));
queue<point>tag;
tag.push(s);
vis[s.x][s.y] = true;
while(!tag.empty()){
tp = tag.front();
tag.pop();
for(int i = 0; i < 4; ++i){
to.x = tp.x + Move[i][0];
to.y = tp.y + Move[i][1];
if(to.x < 0 || to.y < 0 || to.x >= n || to.y >= m || vis[to.x][to.y])
continue;
if(map[to.x][to.y] != '#'){
vis[to.x][to.y] = true;
to.step = tp.step + 1;
if(to.x == p[flag].x && to.y == p[flag].y){
return to;
}
tag.push(to);
}
}
}
return (point){0, 0, -1};
}
int main(){
int x, y;
while(~scanf("%d%d", &n, &m) && n + m){
for(int i = 0; i < n; ++i){
for(int j = 0; j < m; ++j){
cin>>map[i][j];
if(map[i][j] == '@'){
sx = i, sy = j, map[i][j] = '.';
}
}
}
scanf("%d", &ca);
int t[5], cas = 1;
for(int i = 0; i < ca; ++i){
scanf("%d%d", &x, &y);
p[i].x = x - 1, p[i].y = y - 1;
t[i] = i;
cas *= i + 1;
}
int ans = INF;
while(cas--){
int step = 0;
temp = (point){sx, sy, 0};
for(int i = 0; i < ca; ++i){
temp = bfs(temp, t[i]);
if(tp.step != -1){
step = temp.step;
}
else{
step = -1;
break;
}
}
if(step != -1){
ans = step < ans ? step : ans;
}
next_permutation(t, t + ca);
}
if(ans != INF)
printf("%d\n", ans);
else
printf("-1\n");
}
return 0;
}