解题思路:
1.注意到2*2方格中必有一个#,那么最多只有192条通道,可以将所有非‘#’的位置提取出来用邻接表的方式建图,通过bfs搜索目标位置。
2.将三个ghost的位置(a,b,c)作为状态量存储,如果采用邻接矩阵方式存储图,那么转移代价为5*5*5,很容易超时。分析题意可以知道图中结点大部分不是4个方向都能通过,用邻接表可以避免做多余的判断。
代码如下:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cctype> 5 #include <algorithm> 6 #include <queue> 7 #include <vector> 8 using namespace std; 9 const int maxv=192; 10 11 int di[5]={1,-1,0,0,0}; 12 int dj[5]={0,0,1,-1,0}; 13 14 int vis[maxv+2][maxv+2][maxv+2]; 15 typedef struct { 16 int p[3]={0}; 17 int dist=0; 18 }state; 19 20 vector<int> G[maxv+2]; 21 char buff[20][20]; 22 int id[20][20]; 23 24 int w,h,n,vn,ans; 25 int ghost_ascii[3]; 26 state ghost_init_pos,ghost_target_pos; 27 28 int read(){ 29 memset(vis, 0, sizeof vis); 30 memset(ghost_ascii, 0, sizeof ghost_ascii); 31 memset(id, 0, sizeof id); 32 memset(buff, 0, sizeof buff); 33 memset(ghost_init_pos.p, 0, sizeof ghost_init_pos.p); 34 memset(ghost_target_pos.p, 0, sizeof ghost_target_pos.p); 35 scanf("%d%d%d",&w,&h,&n); 36 if(w==0) return 0; 37 38 fgets(buff[0], 16, stdin); 39 40 for(int i=0;i<h;i++) 41 fgets(buff[i], 20, stdin); 42 43 vn=0; 44 for(int i=0;i<h;i++) 45 for(int j=0;j<w;j++) 46 if(buff[i][j]!='#'){ 47 vn++; 48 id[i][j]=vn; 49 } 50 char ch; 51 for(int i=0;i<h;i++){ 52 for(int j=0;j<w;j++){ 53 ch=buff[i][j]; 54 55 if(ch!='#'){ 56 int cur=id[i][j]; 57 58 for(int pos=0;pos<5;pos++){ 59 int x=i+di[pos],y=j+dj[pos]; 60 if(x>=0&&x<h&&y>=0&&y<w&&id[x][y]){ 61 int pre=id[x][y]; 62 G[cur].push_back(pre); 63 } 64 } 65 66 if(islower(ch)){ 67 for(int k=0;k<n;k++) 68 if(!ghost_ascii[k]||ghost_ascii[k]==ch){ 69 ghost_ascii[k]=ch; 70 ghost_init_pos.p[k]=cur; 71 break; 72 } 73 } 74 else if(isupper(ch)){ 75 for(int k=0;k<n;k++){ 76 if(!ghost_ascii[k]||ghost_ascii[k]==ch+'a'-'A'){ 77 ghost_ascii[k]=ch+'a'-'A'; 78 ghost_target_pos.p[k]=cur; 79 break; 80 } 81 } 82 } 83 } 84 } 85 } 86 return 1; 87 } 88 bool check(const state& u,const state& u2){ 89 90 for(int i=0;i<n;i++) 91 for(int j=i+1;j<n;j++) 92 if(u2.p[i]==u2.p[j]) return false; 93 94 for(int i=0;i<n;i++) 95 for(int j=i+1;j<n;j++) 96 if(u2.p[i]==u.p[j]&&u2.p[j]==u.p[i]) return false; 97 return true; 98 } 99 void update(queue<state>& q,const state& u,int i,int j=0,int k=0){ 100 state u2; 101 u2.p[0]=G[u.p[0]][i]; 102 if(n>=2) u2.p[1]=G[u.p[1]][j]; 103 if(n==3) u2.p[2]=G[u.p[2]][k]; 104 if(!vis[u2.p[0]][u2.p[1]][u2.p[2]]&&check(u, u2)) { 105 vis[u2.p[0]][u2.p[1]][u2.p[2]]=1; 106 u2.dist=u.dist+1; 107 q.push(u2); 108 /* 109 for(int m=0;m<n;m++) 110 cout<<u.p[m]<<" "; 111 cout<<" to "; 112 for(int m=0;m<n;m++) 113 cout<<u2.p[m]<<" "; 114 cout<<u2.dist<<endl; 115 */ 116 } 117 } 118 void solve(){ 119 queue<state> q; 120 q.push(ghost_init_pos); 121 vis[ghost_init_pos.p[0]][ghost_init_pos.p[1]][ghost_init_pos.p[2]]=1; 122 while(!q.empty()){ 123 state u=q.front();q.pop(); 124 125 if(memcmp(u.p,ghost_target_pos.p,sizeof ghost_target_pos.p)==0) { 126 ans=u.dist; 127 break; 128 } 129 for(int i=0;i<G[u.p[0]].size();i++){ 130 if(n==1){ 131 update(q, u, i); 132 } 133 else for(int j=0;j<G[u.p[1]].size();j++){ 134 if(n==2){ 135 update(q, u, i,j); 136 } 137 else for(int k=0;k<G[u.p[2]].size();k++){ 138 update(q, u, i,j,k); 139 } 140 } 141 } 142 } 143 printf("%d ",ans); 144 } 145 146 int main() { 147 while(read()){ 148 solve(); 149 150 for(int i=0;i<=maxv;i++) 151 G[i].clear(); 152 } 153 154 return 0; 155 }