这道题思路还是比较清晰的,建图加bfs或双向bfs,其实后者比前者少了将近一半的时间。。
建图可以把某一点所拥有邻接点长度(数目)记录在数组0这个位置,因为这道题使用vector会超时。
#include <iostream> #include <algorithm> #include <cstring> #include <cstdio> #include <vector> #include <queue> #include <map> using namespace std; char a[17][17]; int nex[4][2]= {1,0,0,1,-1,0,0,-1}; int book[17][17],top,book1[400]; int w,h,n; int sta[3],ent[3]; int mat[400][400]; inline bool is_inrage(int x,int y) { if(x<0||x>=h||y<0||y>=w) return false; return true; } int findid(int x,int y) { if(book[x][y]) return book[x][y]; book[x][y]=++top; return book[x][y]; } struct note { int status[3]; int length; int step; note() { status[0]=status[1]=status[2]=0; } }; short vis1[400][400][400],vis2[400][400][400]; bool invilid(int prea,int preb,int nowa,int nowb) { if(nowa==nowb||(prea==nowb&&preb==nowa)) return true; return false; } int bfs(int len) { memset(vis1,0,sizeof(vis1)); memset(vis2,0,sizeof(vis2)); queue<note>que1,que2; note start,ends; ends.length=start.length=len; ends.step=start.step=0; for(int i=0; i<len; i++) { start.status[i]=sta[i]; ends.status[i]=ent[i]; } que1.push(start); que2.push(ends); vis1[start.status[0]][start.status[1]][start.status[2]]=1; vis2[ends.status[0]][ends.status[1]][ends.status[2]]=1; int ac[3],flag; struct note u1,v1,u2,v2; while(!que1.empty()||!que2.empty()) { if(!que1.empty()) { u1=que1.front(); que1.pop(); for(int i=1; i<=mat[u1.status[0]][0]; i++) { ac[0]=mat[u1.status[0]][i]; for(int j=1; j<=mat[u1.status[1]][0]; j++) { ac[1]=mat[u1.status[1]][j]; if(invilid(u1.status[0],u1.status[1],ac[0],ac[1])) continue; for(int h=1; h<=mat[u1.status[2]][0]; h++) { ac[2]=mat[u1.status[2]][h]; if(len==3) if(invilid(u1.status[0],u1.status[2],ac[0],ac[2])) continue; if(len==3) if(invilid(u1.status[1],u1.status[2],ac[1],ac[2])) continue; v1.step=u1.step+1; v1.length=u1.length; v1.status[0]=ac[0]; v1.status[1]=ac[1]; v1.status[2]=ac[2]; if(vis1[v1.status[0]][v1.status[1]][v1.status[2]]) continue; vis1[v1.status[0]][v1.status[1]][v1.status[2]]=v1.step; que1.push(v1); int a1,b1,c1; a1=v1.status[0];b1=v1.status[1];c1=v1.status[2]; if(vis2[a1][b1][c1]) return vis1[a1][b1][c1]+vis2[a1][b1][c1]; } } } } if(!que2.empty()) { u2=que2.front(); que2.pop(); for(int i=1; i<=mat[u2.status[0]][0]; i++) { ac[0]=mat[u2.status[0]][i]; for(int j=1; j<=mat[u2.status[1]][0]; j++) { ac[1]=mat[u2.status[1]][j]; if(invilid(u2.status[0],u2.status[1],ac[0],ac[1])) continue; for(int h=1; h<=mat[u2.status[2]][0]; h++) { ac[2]=mat[u2.status[2]][h]; if(len==3) if(invilid(u2.status[0],u2.status[2],ac[0],ac[2])) continue; if(len==3) if(invilid(u2.status[1],u2.status[2],ac[1],ac[2])) continue; v2.step=u2.step+1; v2.length=u2.length; v2.status[0]=ac[0]; v2.status[1]=ac[1]; v2.status[2]=ac[2]; if(vis2[v2.status[0]][v2.status[1]][v2.status[2]]) continue; vis2[v2.status[0]][v2.status[1]][v2.status[2]]=v2.step; que2.push(v2); int a2,b2,c2; a2=v2.status[0];b2=v2.status[1];c2=v2.status[2]; if(vis1[a2][b2][c2]) return vis1[a2][b2][c2]+vis2[a2][b2][c2]; } } } } } return -1; } struct node { int x,y; char v; node() {} node(int xx,int yy,char vv):x(xx),y(yy),v(vv) {} bool operator < (const node &another) const { return v<another.v; } }; int main() { while(scanf("%d%d%d",&w,&h,&n),w+h+n) { char ch[20]; memset(book,0,sizeof(book)); node t1[3],t2[3]; int s1=0,s2=0; memset(mat,0,sizeof(mat)); getchar(); for(int i=0; i<h; i++) { gets(ch); for(int j=0; j<w; j++) { a[i][j]=ch[j]; if('a'<=ch[j]&&ch[j]<='z') t1[s1++]=node(i,j,ch[j]); if('A'<=ch[j]&&ch[j]<='Z') t2[s2++]=node(i,j,ch[j]); } } int nx,ny,idpre,idnex; top=0; for(int i=0; i<h; i++) { for(int j=0; j<w; j++) { for(int k=0; k<4; k++) { if(a[i][j]=='#') continue; nx=i+nex[k][0]; ny=j+nex[k][1]; if(is_inrage(nx,ny)&&a[nx][ny]!='#') { idpre=findid(i,j); idnex=findid(nx,ny); int lenth=++mat[idpre][0]; mat[idpre][lenth]=idnex; } } } } for(int i=0; i<=top; i++) { ++mat[i][0]; mat[i][mat[i][0]]=i; } sort(t1,t1+n); sort(t2,t2+n); for(int i=0; i<n; i++) { sta[i]=findid(t1[i].x,t1[i].y); ent[i]=findid(t2[i].x,t2[i].y); // cout<<sta[i]<<" "<<ent[i]<<endl; } printf("%d ",bfs(n)); } return 0; }