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..
*/

  


时间: 2024-08-10 00:05:34

nyoj 999——师傅又被妖怪抓走了——————【双广搜】的相关文章

nyist 999 师傅又被妖怪抓走了 【双广搜 || BFS +状态压缩】

题目:nyist 999 师傅又被妖怪抓走了 分析:在一个图中只要看到D点和E点就行的最小步数,看到的定义是:也就是说两个人在同一行或者同一列,并且中间没有障碍物或者没有其他人就可以看到对方. 所以可以先预处理地图,把D点和E点所在的行列的' .'扩展为d和e,然后只要搜到d和e就可以,问题是只有d和e同时搜到才行,直接广搜肯定不行,我们可以在搜到d点之后然后在从当前点广搜e点,或者e点广搜d点,这样第一次搜到的点不一定是最优的,所以需要枚举所有情况才行,时间复杂度较高. 比较好的一种方法是BF

nyoj999 师傅又被妖怪抓走了 (预处理+bfs+状态压缩)

题目999 题目信息 执行结果 本题排行 讨论区 师傅又被妖怪抓走了 时间限制:1000 ms | 内存限制:65535 KB 难度:3 描写叙述 话说唐僧复得了孙行者,师徒们一心同体,共诣西方.自宝象国救了公主,承君臣送出城西.沿路饥餐渴饮,悟空便为师傅去化斋.等悟空回来,悟净慌慌张张的对悟空说:"不好了,不好了",还没等悟净说完,悟空说:"师傅又被妖怪抓走了",悟净:"NO!" ,悟空一脸茫然.悟净:"师傅和二师兄都被妖怪抓走了&q

NYOJ999 师傅又被妖怪抓走了

只记得当下的眼疼 , ok 各种数据也试了 , 就是 他娘的不对 , 我也是醉了 . 也是日了最野的狗 附上日了哮天犬的代码 , 这个题 先放放, 一段时间后再试试 , 明天开始状态压缩吧 .为期两天 1 #include<stdio.h> 2 #include<string.h> 3 #include<math.h> 4 #include<iostream> 5 #include<algorithm> 6 #include<queue&g

NYOJ 284 坦克大战 &amp;&amp; POJ 2312 Battle City (广搜+优先队列)

链接:click here~~ 题意: 描述 Many of us had played the game "Battle city" in our childhood, and some people (like me) even often play it on computer now. What we are discussing is a simple edition of this game. Given a map that consists of empty space

shu_1548 悟空的难题(大师兄,师傅被妖怪抓走啦!)

http://202.121.199.212/JudgeOnline/problem.php?cid=1078&pid=17 分析:  直接暴力了... 代码: #include <stdio.h> #include <iostream> using namespace std; #define MAXN 2004 #define inf 0x3f3f3f3f int k[MAXN],f[MAXN]; int my_abs(int a) { return a<0? -

openjudge 大师兄,师傅被妖怪抓走啦

描述 孙悟空听到沙僧大喊一句:“大师兄,师傅被妖怪抓走啦!”于是孙悟空直追白骨精而去.孙悟空在一条长度为L的森林小路上飞奔,上面有L+1个整点,依次为0,1,2……L.白骨精会使用一种大范围的攻击法术,产生N个能量球,其中第i个能量球的能量值为f[i],落在小路的整点k[i]上.当孙悟空的位置离能量球i的距离为s时,会受到f[i]-s的伤害,如果f[i]-s计算出的伤害为负值,则判定为0.孙悟空虽然救师心切,但也不能葬身于白骨精的法术之中,因此他想知道应该躲在哪一个整点处,才能让自己受到的总伤害

NYOJ 483 Nightmare 【广搜】+【无标记】

Nightmare 时间限制:1000 ms  |  内存限制:65535 KB 难度:4 描述 Ignatius had a nightmare last night. He found himself in a labyrinth with a time bomb on him. The labyrinth has an exit, Ignatius should get out of the labyrinth before the bomb explodes. The initial e

nyoj 523 双向广搜

题目链接: http://acm.nyist.net/JudgeOnline/problem.php?pid=523 #include<iostream> #include<cstdio> #include<queue> using namespace std; /* 用普通搜索TLE,已知起点和终点,可以考虑双向广搜或A*算法加速搜索 双向广搜,一个方向从出发点向终点搜索,一个方向从终点向出发点搜索,搜索到相同的结点时,即找到最短路径. */ const int N

深搜 ,广搜,队列 nyoj 27 水池数目

水池数目 时间限制:3000 ms  |  内存限制:65535 KB 难度:4 描述 南阳理工学院校园里有一些小河和一些湖泊,现在,我们把它们通一看成水池,假设有一张我们学校的某处的地图,这个地图上仅标识了此处是否是水池,现在,你的任务来了,请用计算机算出该地图中共有几个水池. 输入 第一行输入一个整数N,表示共有N组测试数据 每一组数据都是先输入该地图的行数m(0<m<100)与列数n(0<n<100),然后,输入接下来的m行每行输入n个数,表示此处有水还是没水(1表示此处是水