紫书上的代码 有意思的是刘大牛用了位运算表示状态 其实用结构体也可以 输入用getsc++不让用, 后面换了fgets 引用了
https://zhidao.baidu.com/question/427775494.html 的答案
fgets的原型是 char* fgets(char* s, int n, FILE* fp); 参数数量比较多,有3个。而fgets相比于gets有一个显著的差别就是fgets会将行末的换行符算到读入的字符串里面。所以相同且正常(输入无错误,缓冲区够大)的情况下,fgets读入的字符串会比gets在末尾'\0'前面多一个换行符;行长度超出缓冲区大小时只读入前 n-1 个字符。因此, gets(s); 相当于 fgets(s, sizeof(s), stdin); if(s[strlen(s) - 1] == '\n') s[strlen(s) - 1] = '\0'; // 去掉换行符 其实,末尾这个换行符是另有妙用的。
还有鬼数量不足3个设置假鬼也很有意思 设置一个假鬼点自环,同时只有他自己能到这个点,他也只有一条自环边,所以不影响正确答案。这样可以有效减少代码量
#include<bits/stdc++.h>
using namespace std;
int w,h,n;
int cnt=0;
char maze[25][25];
int x[405],y[405],deg[405];
int id[20][20];
int s[4],t[4];
int G[250][6];
int dx[]={0,1,-1,0,0};
int dy[]={0,0,0,1,-1};
inline bool conflict(int a, int b, int a2, int b2) {
return a2 == b2 || (a2 == b && b2 == a);
}
inline int ID(int a, int b, int c) {
return (a<<16)|(b<<8)|c; //也可以用个结构存
}
int d[200][200][200];
int bfs(){
queue<int>q;
memset(d,-1,sizeof(d));
q.push(ID(s[0],s[1],s[2]));
d[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; //读取出8 8 8这3个8位
if(a==t[0]&&b==t[1]&&c==t[2])return d[a][b][c];
for(int i=0;i<deg[a];i++){
int a2=G[a][i];
for(int j=0;j<deg[b];j++){
int b2=G[b][j];
if(conflict(a,b,a2,b2))continue;
for(int k = 0; k < deg[c]; k++) {
int c2 = G[c][k];
if(conflict(a, c, a2, c2)) continue;
if(conflict(b, c, b2, c2)) continue;
if(d[a2][b2][c2] != -1) continue;
d[a2][b2][c2] = d[a][b][c]+1;
q.push(ID(a2, b2, c2));
}
}
}
}
return -1;
}
int main(){
while(scanf("%d%d%d",&w,&h,&n)==3&&w){
memset(deg,0,sizeof(deg));
cnt=0;
getchar();
for(int i=0;i<h;i++){
fgets(maze[i],20,stdin);
for(int j=0;j<w;j++){
if(maze[i][j]!='#'){
x[cnt]=i;y[cnt]=j;id[i][j]=cnt;
if(islower(maze[i][j]))s[maze[i][j]-'a']=cnt;
else if(isupper(maze[i][j]))t[maze[i][j]-'A']=cnt;
cnt++;
}
}
}
for(int i=0;i<cnt;i++){
deg[i]=0;
for(int j=0;j<5;j++){//注意 还有停下来的操作
int tx=x[i]+dx[j];
int ty=y[i]+dy[j];
if(tx>=0&&tx<h&&ty>=0&&ty<w&&maze[tx][ty]!='#'){
G[i][deg[i]++]=id[tx][ty];
}
}
}
//设置假鬼就一个方向自环 等于设置了一个虚拟点 这样可以减少代码量 把1 2个鬼的情况模拟成3个的情况又对答案没有影响
if(n<=2){
deg[cnt]=1;G[cnt][0]=cnt;s[2]=t[2]=cnt++;
}
if(n<=1){
deg[cnt]=1;G[cnt][0]=cnt;s[1]=t[1]=cnt++;
}
printf("%d\n",bfs());
}
return 0;
}