传送门
给出一个起点,4个终点,要求从起点出发,每个终点都走到的最短距离
一般来说,如果只有一个终点,那么就直接bfs,但是有4个终点,用状压dp
设置一个vis[N][N][1 << 4]来设置记录
且每一个点存4个变量,x,y,key和step,key表示当前的状压情况
那么不断进行bfs,如果遇到终点,那么进行状压一下u.key | (1 << (s[xx][yy] - '0'))即可,同时更新key即可
那么如果说nex.key == (1 << k) - 1,也就是说4个终点都走过了,那么就直接返回答案即可
第一次遇到状压bfs,记录下,感觉好神奇啊,大雾
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <map>
#include <set>
#include <cmath>
#include <stack>
#include <algorithm>
#include <ctime>
using namespace std;
#define ll long long
const int N = 105;
char s[N][N];
int dir[][2] = {1, 0, -1, 0, 0, 1, 0, -1};
int n, m, k;
int sx, sy;
bool vis[N][N][1 << 4]; // 状压数组
struct Node{
int x, y, key, step;
};
bool check(int x, int y){
if(x < 1 || x > n || y < 1 || y > m || s[x][y] == '#') return 0;
return 1;
}
int bfs(){
queue<Node> q;
Node now;
now.x = sx, now.y = sy;
now.step = 0; now.key = 0;
q.push(now);
while(!q.empty()) {
Node u = q.front();
q.pop();
for(int i = 0; i < 4; i++) {
int xx = dir[i][0] + u.x;
int yy = dir[i][1] + u.y;
if(!check(xx, yy)) continue;
Node nex;
if(s[xx][yy] >= '0' && s[xx][yy] <= '3') { //终点,状压一下,再继承上一个点的信息
if(!vis[xx][yy][u.key]) {
vis[xx][yy][u.key | (1 << (s[xx][yy] - '0'))] = 1;
nex.x = xx, nex.y = yy, nex.step = u.step + 1, nex.key = u.key | (1 << (s[xx][yy] - '0'));
if(nex.key == (1 << k) - 1) return nex.step; // 点走完了
q.push(nex);
}
}else { // 普通点,继承上一个点的信息
if(!vis[xx][yy][u.key]) {
vis[xx][yy][u.key] = 1;
nex.x = xx, nex.y = yy, nex.key = u.key, nex.step = u.step + 1;
q.push(nex);
}
}
}
}
return -1;
}
int main(){
while(~scanf("%d%d", &n, &m)) {
if(n == 0 && m == 0) break;
bool f = 1;
for(int i = 1; i <= n; i++) scanf("%s", s[i] + 1);
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++){
if(s[i][j] == '@') sx = i, sy = j; // 起点
}
}
memset(vis, 0, sizeof(vis));
scanf("%d", &k);
for(int i = 0; i < k; i++) {
int x, y;
scanf("%d%d", &x, &y);
if(s[x][y] == '#') f = 0;
else if(s[x][y] == '@') { // 把所有的终点设置为相应的数字,方便进行状压
s[x][y] = i + '0';
vis[x][y][1 << i] = 1;
} else s[x][y] = i + '0';
}
if(!f) printf("-1
");
else {
printf("%d
", bfs());
}
}
return 0;
}