nyoj 999——师傅又被妖怪抓走了——————【双广搜】

师傅又被妖怪抓走了

时间限制:1000 ms  |  内存限制:65535 KB
难度:3
 
描述

话说唐僧复得了孙行者,师徒们一心同体,共诣西方。自宝象国救了公主,承君臣送出城西,沿路饥餐渴饮,悟空便为师傅去化斋,等悟空回来,悟净慌慌张张的对悟空说:“不好了,不好了”,还没等悟净说完,悟空说:“师傅又被妖怪抓走了”,悟净:“NO!” ,悟空一脸茫然,悟净:“师傅和二师兄都被妖怪抓走了”。悟空(晕!)。为了防止悟空救人,妖怪先把唐憎和八戒分别藏起来,如果悟空在T分钟之后还没找到人,那必定是被妖怪吃掉了。假设悟空在一个n行m列的矩阵内,悟空在每一分钟可以走到上,下,左,右的其中的一个可以走的位置,每次只能走一步。我们把发现定义为可以直接看到对方,也就是说两个人在同一行或者同一列,并且中间没有障碍物或者没有其他人就可以看到对方。

 
输入
有多组测试数据,每组首先是三个正整数n , m (3<=n,m<=100), T,(0<=T<=100) 分别代表行数,列数,规定的时间。接下来n 行,每行 m 个字符。其中’ S ’ 代表悟空的位置,’ D ’代表师傅位置,’ E ’代表八戒的位置。并且保证都只有一个. ’ X ’代表墙 ,’ . ’代表空地 .
输出
每组先输出一行Case c:(c表示当前的组数,从1开始计数);
接下来一行,如果悟空可以在规定时间内找到两人,则输出最少需要的时间,否则输出-1。
样例输入
5 6 3 
XXD...
....E.
....X.
....S. 
......
5 6 3 
XDX... 
....E. 
...... 
....S. 
...... 
5 6 8 
XXDX.. 
.XEX.. 
...... 
....S. 
......
样例输出
Case 1:
-1 
Case 2:
3 
Case 3:
-1


解题思路:首先将图处理一下,处理成可以表示在某点可以找到某人或两人。然后在搜到某人后搜另外一个或者同时搜到两人。如果搜到其中一人,然后再搜另外一人。这就是双广搜,先搜一个中间结果,再在这个基础上搜另外未完成的结果。但是需注意,不是先搜到的就是最优结果。所以需要把能成功搜到两人的路径都搜一遍。取最小值。

#include<bits/stdc++.h>
using namespace std;
char Map[105][105];
int mark[105][105];
int vis[105][105];
int f[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
int n,m,ans,t;
const int INF=1e9;
struct Monkey{
    int x,y;
    int step;
};
bool CanTravle(int ti,int tj){  //判断是否可以走
    if(Map[ti][tj]=='X'||Map[ti][tj]=='D'||Map[ti][tj]=='E'){
        return 0;
    }else{
        return 1;
    }
}
char trans(int i,int j,int cas){    //转化字符
    if(cas&&Map[i][j]=='e'||(!cas&&Map[i][j]=='d')){
        return 'o';
    }
    return cas ? 'd': 'e';
}
void Change(int si,int sj,int cas){ //把D、E所在的行列能走的变为d和e,把交叉点变为o
    int i,j;
    for(i=si+1;i<=n&&CanTravle(i,sj);i++)
        Map[i][sj]=trans(i,sj,cas);
    for(i=si-1;i>=1&&CanTravle(i,sj);i--)
        Map[i][sj]=trans(i,sj,cas);
    for(j=sj+1;j<=m&&CanTravle(si,j);j++)
        Map[si][j]=trans(si,j,cas);
    for(j=sj-1;j>=1&&CanTravle(si,j);j--)
        Map[si][j]=trans(si,j,cas);
}
queue<Monkey>Q;
queue<Monkey>Qde;
int BFSde(int cas){ //在找到八戒或师父后找另外一个
    Monkey st,tmp;
    while(!Qde.empty()){
        st=Qde.front();
        Qde.pop();
        if(st.step>t)
            continue;
        if(cas&&Map[st.x][st.y]=='e'||(!cas&&Map[st.x][st.y]=='d')||Map[st.x][st.y]=='o'){
             return st.step;
        }
        int i,j,tx,ty,tsp;
        for(i=0;i<4;i++){
            tx=st.x+f[i][0];
            ty=st.y+f[i][1];
            if(tx<=n&&tx>=1&&ty<=m&&ty>=1&&(!vis[tx][ty])&&CanTravle(tx,ty)){
                tsp=st.step+1;
                vis[tx][ty]=1;
                tmp.x=tx,tmp.y=ty,tmp.step=tsp;
                Qde.push(tmp);
            }
        }
    }
    return INF;
}
void BFS(){ //找到八戒或师父或同时找到两人
    Monkey st,tmp;
    ans=INF;
    while(!Q.empty()){
       st=Q.front();
       Q.pop();
       if(st.step>t)
        continue;
       if(Map[st.x][st.y]=='o'){
            ans=min(ans,st.step);
       }else if(Map[st.x][st.y]=='e'){
            while(!Qde.empty())
                Qde.pop();
            Qde.push(st);
            memset(vis,0,sizeof(vis));
            vis[st.x][st.y]=1;
            ans=min(ans,BFSde(0));
       }else if(Map[st.x][st.y]=='d'){
           while(!Qde.empty())
                Qde.pop();
            Qde.push(st);
            memset(vis,0,sizeof(vis));
            vis[st.x][st.y]=1;
            ans=min(ans,BFSde(1));
       }
       int tx,ty,tsp,i,j;
       for(i=0;i<4;i++){
            tx=st.x+f[i][0];
            ty=st.y+f[i][1];
            if(tx>=1&&tx<=n&&ty>=1&&ty<=m&&CanTravle(tx,ty)&&(!mark[tx][ty])){
                mark[tx][ty]=1;
                tsp=st.step+1;
                tmp.x=tx,tmp.y=ty,tmp.step=tsp;
                Q.push(tmp);
            }
       }
    }
}
int main(){
    int i,j,k,cnt=0;
    Monkey st;
    while(scanf("%d%d%d",&n,&m,&t)!=EOF){
        memset(mark,0,sizeof(mark));
        for(i=1;i<=n;i++){
            for(j=1;j<=m;j++){
                cin>>Map[i][j];
                if(Map[i][j]=='S'){
                    st.x=i;
                    st.y=j;
                    st.step=0;
                }
            }
        }
        for(i=1;i<=n;i++){  //处理图
            for(j=1;j<=m;j++){
                if(Map[i][j]=='D'){
                    Change(i,j,1);
                }else if(Map[i][j]=='E'){
                    Change(i,j,0);
                }
            }
        }
        while(!Q.empty())
            Q.pop();
        Q.push(st);
        mark[st.x][st.y]=1;
        BFS();
        if(ans>t){
            printf("Case %d:\n-1\n",++cnt);
        }else{
            printf("Case %d:\n%d\n",++cnt,ans);
        }
    }
    return 0;
}


/*

5 6 30
XDX...
....E.
...S..
......
......

7 6 5
......
.D.X..
X.X...
X.....
X.X...
.E....
...S..
*/

  




posted @ 2015-06-29 18:09  tcgoshawk  阅读(238)  评论(0编辑  收藏  举报