一直在纠结怎么样表示找到了人,,,开始时竟灰笨得设两个BOOL。后来参考别人的可以使用二进制位。
另外,此处有一个剪枝就是,就到达该点之后的状态的found(即找到人的状态)在之前已出现过,可以剪去。
#include <iostream> #include <cstring> #include <algorithm> #include <queue> using namespace std; bool flag[105][105][4]; char map[105][105]; int see[105][105]; int n,m,lim,sx,sy; int dir[4][2]={ {0,1}, {0,-1}, {1,0}, {-1,0} }; struct Status{ int x,y; int found,cnt; Status(){ found=0; } }; void Init(){ memset(see,0,sizeof(see)); for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ if(map[i][j]=='S'){ sx=i,sy=j; } if(map[i][j]=='X') continue; int ii=i,jj=j; while(jj>=1&&(map[ii][jj]=='.'||map[ii][jj]=='S')) jj--; if(jj>=1&&map[ii][jj]=='D') see[i][j]|=1; if(jj>=1&&map[ii][jj]=='E') see[i][j]|=2; ii=i,jj=j; while(jj<=m&&(map[ii][jj]=='.'||map[ii][jj]=='S')) jj++; if(jj<=m&&map[ii][jj]=='D') see[i][j]|=1; if(jj<=m&&map[ii][jj]=='E') see[i][j]|=2; ii=i,jj=j; while(ii<=n&&(map[ii][jj]=='.'||map[ii][jj]=='S')) ii++; if(ii<=n&&map[ii][jj]=='D') see[i][j]|=1; if(ii<=n&&map[ii][jj]=='E') see[i][j]|=2; ii=i,jj=j; while(ii>=1&&(map[ii][jj]=='.'||map[ii][jj]=='S')) ii--; if(ii>=1&&map[ii][jj]=='D') see[i][j]|=1; if(ii>=1&&map[ii][jj]=='E') see[i][j]|=2; } } } bool ok(int x,int y){ if(x>=1&&x<=n&&y>=1&&y<=m) return true; return false; } bool slove(){ memset(flag,false,sizeof(flag)); Status s,t; s.x=sx,s.y=sy,s.found=see[s.x][s.y],s.cnt=0; // cout<<s.found<<endl; queue<Status>que; que.push(s); while(!que.empty()){ s=que.front(); que.pop(); if(s.cnt>lim) return false; else if(s.found==3){ printf("%d ",s.cnt); return true; } flag[s.x][s.y][s.found]=true; for(int i=0;i<4;i++){ t=s; t.x=s.x+dir[i][0]; t.y=s.y+dir[i][1]; if(map[t.x][t.y]=='D'||map[t.x][t.y]=='E'||map[t.x][t.y]=='X'||!ok(t.x,t.y)) continue; t.found|=see[t.x][t.y]; if(flag[t.x][t.y][t.found]) continue; flag[t.x][t.y][t.found]=true; t.cnt++; que.push(t); } } return false; } int main(){ int T,t=0; scanf("%d",&T); while(T--){ scanf("%d%d%d",&n,&m,&lim); for(int i=1;i<=n;i++) scanf("%s",map[i]+1); Init(); printf("Case %d: ",++t); if(!slove()){ puts("-1"); } } return 0; }