总结
例题
1
普通bfs
重点在代码里
//以下关于编码解码的内容,以后再看,现在注重算法
#include<cstdio>
#include<cctype>
#include<queue>
#include<cstring>
using namespace std;
const int N = 20;
const int MAXN = 200;// 75% cells plus 2 fake nodes
const int mx[] = {-1, 1, 0, 0, 0};
const int my[] = {0, 0, -1, 1, 0};//包括不移动
inline int ID(int a, int b, int c) {//编码
return (a<<16)|(b<<8)|c;
}
int r, c, n;
int s[3], t[3];//三只鬼的起点&终点
int G[MAXN][6];
//重点1 : G用来把空格重组成一张图,G[i][0]表示标号为i的空格周围能走的格子数//邻接表嘛
//G[i][1~5]表示下一步鬼从i可以走到的空格的编号 (其实也可以记录dir
inline int comflict(int a, int b, int a2, int b2) {
// return (a==a2&&b==b2) || (a==b2&&b==a2); 这是我傻了...这不是坐标!这是编号
return a2 == b2 || (a2 == b && b2 == a);//判断同时移动的时候是否冲突
}
int dis[MAXN][MAXN][MAXN];
int bfs() {
queue<int> q;
memset(dis, -1, sizeof(dis));
q.push(ID(s[0], s[1], s[2]));
dis[s[0]][s[1]][s[2]] = 0;
while(!q.empty()) {
int u = q.front(); q.pop();
int a = (u>>16)&0xff, b = (u>>8)&0xff, c = u&0xff;//解码
if(a==t[0] && b==t[1] && c==t[2]) return dis[a][b][c];
for(int i = 1; i <= G[a][0]; i++) {
int a2 = G[a][i];
for(int j = 1; j <= G[b][0]; j++) {
int b2 = G[b][j];
if(comflict(a, b, a2, b2)) continue;
for(int k = 1; k <= G[c][0]; k++) {
int c2 = G[c][k];
if(comflict(a, c, a2, c2)) continue;
if(comflict(b, c, b2, c2)) continue;
if(dis[a2][b2][c2] != -1) continue;
dis[a2][b2][c2] = dis[a][b][c]+1;
q.push(ID(a2, b2, c2));
}
}
}
}
return -1;
}
int main() {
while(scanf("%d%d%d
", &c, &r, &n) == 3 && n) {//记得在这加上“
”
char M[N][N];//以后这样的,不是全局变量的,只在main里面声明就行了,不用init了
for(int i = 0; i < r; i++) {
fgets(M[i], 20, stdin);
// printf(" %d
", i);
}
//从原图中抽出空格,并确定初末位置
int cnt, x[MAXN], y[MAXN], id[MAXN][MAXN];//用id[][]来给G[][]赋值,这样会方便很多
cnt = 0; //cnt:空格数(顺便编号
for(int i = 0; i < r; i++)
for(int j = 0; j < c; j++) if(M[i][j] != '#') {
x[cnt] = i; y[cnt] = j; id[i][j] = cnt;
if(islower(M[i][j])) s[M[i][j] - 'a'] = cnt;
else if(isupper(M[i][j])) t[M[i][j] - 'A'] = cnt;
cnt++;
}
//用空格,邻接表建图: 即计算G
for(int i = 0; i < cnt; i++) {
G[i][0] = 0;
for(int dir = 0; dir < 5; dir++) {
int x2 = x[i]+mx[dir], y2 = y[i]+my[dir];
if(M[x2][y2] != '#') G[i][++G[i][0]] = id[x2][y2];//由题意:没必要判越界
}
}
//重点2: 添加fake节点,简化code
if(n <= 2) {G[cnt][0] = 1; G[cnt][1] = cnt; s[2] = t[2] = cnt; cnt++;}
if(n <= 1) {G[cnt][0] = 1; G[cnt][1] = cnt; s[1] = t[1] = cnt; cnt++;}
printf("%d
", bfs());
}
return 0;
}