hdu 1429 1885 广搜
1429题意:这次魔王汲取了上次的教训,把Ignatius关在一个n*m的地牢里,并在地牢的某些地方安装了带锁的门,钥匙藏在地牢另外的某些地方。刚开始Ignatius被关在(sx,sy)的位置,离开地牢的门在(ex,ey)的位置。Ignatius每分钟只能从一个坐标走到相邻四个坐标中的其中一个。魔王每t分钟回地牢视察一次,若发现Ignatius不在原位置便把他拎回去。经过若干次的尝试,Ignatius已画出整个地牢的地图。现在请你帮他计算能否再次成功逃亡。只要在魔王下次视察之前走到出口就算离开地牢,如果魔王回来的时候刚好走到出口或还未到出口都算逃亡失败。
分析:
用b[x][y][s]代表在x,y位置,状态为s的最小步数。其中s为状态压缩,第i位为1表示钥匙i已拿到。
const int maxn=800000; int n,m,limit,sx,sy,ex,ey,ans; string str[20]; int x[maxn],y[maxn],s[maxn],d[maxn],pp; int b[25][25][2024]; int t1[]={-1,0,1,0},t2[]={0,1,0,-1}; queue<int> q; stack<int> sta; void read(){ while(!q.empty())q.pop(); while(!sta.empty())sta.pop(); memset(b,1,sizeof(b)); int f=0; ans=-1; pp=1; for(int i=0;i<n;i++) { cin>>str[i]; for(int j=0;j<m;j++){ if(str[i][j]=='@') sx=i, sy=j, f=1; else if(str[i][j]=='^') ex=i, ey=j; if(f){ x[0]=i; y[0]=j; s[0]=d[0]=f=0; q.push(0); } } } } void solve(){ while(!q.empty()){ int p, v=q.front(); q.pop(); for(int i=0;i<4;i++){ int xx=x[v]+t1[i], yy=y[v]+t2[i]; if(!(xx>=0 && xx<n && yy>=0 && yy<m)) continue; char ch=str[ xx ][ yy ]; if(!(ch=='*'||(ch>='A'&&ch<='J'&&0==(s[v]&(1<<(ch-'A')))))){ if(sta.empty()) p=pp++; else {p=sta.top(); sta.pop();} x[p]=xx; y[p]=yy; s[p]=s[v]; d[p]=d[v]+1; if(ch>='a'&&ch<='j') s[p]|=1<<(ch-'a'); if(d[p]<b[ x[p] ][ y[p] ][ s[p] ] && d[p]<limit) {b[ x[p] ][ y[p] ][ s[p] ]=d[p];q.push(p);} if(x[p]==ex&&y[p]==ey&&d[p]<limit) {ans=d[p];return;} } } sta.push(v); } } int main(){ while(cin>>n>>m>>limit){ read(); solve(); cout<<ans<<endl; } return 0; }
1885 有多个出口或没有出口 四种门和钥匙 问最少多少步能出来
const int maxn=800000; int n,m,sx,sy,ans; string str[100]; int x[maxn],y[maxn],s[maxn],d[maxn],pp; int b[100][100][16]; int t1[]={-1,0,1,0},t2[]={0,1,0,-1}; queue<int> q; stack<int> sta; void read(){ while(!q.empty())q.pop(); while(!sta.empty())sta.pop(); memset(b,1,sizeof(b)); int f=0; ans=-1; pp=1; for(int i=0;i<n;i++) { cin>>str[i]; for(int j=0;j<m;j++){ if(str[i][j]=='*') sx=i, sy=j, f=1; else if(str[i][j]=='Y') str[i][j]='A'; else if(str[i][j]=='R') str[i][j]='C'; else if(str[i][j]=='G') str[i][j]='D'; else if(str[i][j]=='y') str[i][j]='a'; else if(str[i][j]=='r') str[i][j]='c'; else if(str[i][j]=='g') str[i][j]='d'; if(f){ x[0]=i; y[0]=j; s[0]=d[0]=f=0; q.push(0); } } } } void solve(){ while(!q.empty()){ int p, v=q.front(); q.pop(); for(int i=0;i<4;i++){ int xx=x[v]+t1[i], yy=y[v]+t2[i]; if(!(xx>=0 && xx<n && yy>=0 && yy<m)) continue; char ch=str[ xx ][ yy ]; if(!(ch=='#'||(ch>='A'&&ch<='D'&&0==(s[v]&(1<<(ch-'A')))))){ if(sta.empty()) p=pp++; else {p=sta.top(); sta.pop();} x[p]=xx; y[p]=yy; s[p]=s[v]; d[p]=d[v]+1; if(ch>='a'&&ch<='d') s[p]|=1<<(ch-'a'); if(d[p]<b[ x[p] ][ y[p] ][ s[p] ] ) {b[ x[p] ][ y[p] ][ s[p] ]=d[p];q.push(p);} if(str[x[p]][y[p]]=='X') {ans=d[p];return;} } } sta.push(v); } } int main(){ while(cin>>n>>m){ if(n==0)break; read(); solve(); if(ans==-1)cout<<"The poor student is trapped!"<<endl; else cout<<"Escape possible in "<<ans<<" steps."<<endl; } return 0; }