zoukankan      html  css  js  c++  java
  • 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:
    -1
    ",++cnt);
            }else{
                printf("Case %d:
    %d
    ",++cnt,ans);
            }
        }
        return 0;
    }
    
    
    /*
    
    5 6 30
    XDX...
    ....E.
    ...S..
    ......
    ......
    
    7 6 5
    ......
    .D.X..
    X.X...
    X.....
    X.X...
    .E....
    ...S..
    */
    

      




  • 相关阅读:
    bzoj 2337 [HNOI2011]XOR和路径【高斯消元+dp】
    bzoj 3196 Tyvj 1730 二逼平衡树【线段树 套 splay】
    bzoj 3528 [Zjoi2014]星系调查【树链剖分+数学】
    bzoj 2127 happiness【最小割+dinic】
    bzoj 3110 [Zjoi2013]K大数查询【树套树||整体二分】
    bzoj 4137 [FJOI2015]火星商店问题【CDQ分治+可持久化trie】
    运用背景橡皮擦抠透明郁金香
    使用快速通道抠荷花
    抠图总结
    花纹的选区
  • 原文地址:https://www.cnblogs.com/chengsheng/p/4608213.html
Copyright © 2011-2022 走看看