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;
}
View Code

 

posted @ 2013-06-20 13:42  心向往之  阅读(143)  评论(0编辑  收藏  举报