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


    题目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

    这道题让我非常焦灼啊。。。开个玩笑 哈哈

    这道题的发现定义为能够直接看到对方。所以是不能走X D E 仅仅能是看到

    所以在录入数据的时候 我们就提前做好预处理。

    把D E的四个方向 能看到的地方都处理一下

    然后就是bfs了 而在这里 我提交了几次 发现都不正确 后来无意中的一个数据启示了我

    2 3 1

    .S.

    DXE

    输出-1

    2 3 3

    .S.

    DXE

    输出3

    聪明的你 看出来了吗?假设我们用通常的vis数组标记走过的路径
    ,对于第二条測试数据 仅仅会输出-1  由于它不会走回头路 。我又存在侥幸的心理 不用vis数组标记了 发现 果然TLE

     然后就是不做了 走在路上还在想 到底在这里该怎么优化 。。。果然 睡觉的时候被我想到了 今天早上一大早 就起来做了。

    详细方法是 假设又定义了两个数组visE【x】【y】 visD【x】【y】分别记录在x,y点 是否已经找到过E 或D  。

    当某个点已经遍历过

    我们再推断当前的visD 和visE和之前的是否一致  假设一致 我们就不用走 假设不一致 证明我们在其他点找到了D或E  如今要回来。

    详细看代码把

    #include <stdio.h>
    #include <string.h>
    #include <queue>
    #include <algorithm>
    using namespace std;
    int n,m;
    int t;
    int s1,s2;
    int d1,d2;
    int e1,e2;
    int dir[4][2]={1,0,0,1,-1,0,0,-1};
    char map[105][105];
    bool visD[105][105];
    bool visE[105][105];
    bool vis[105][105];
    struct node
    {
    	int x,y;
    	int step;
    	bool isfindD;
    	bool isfindE;
    	friend bool operator<(node a,node b)
    	{
    		return a.step>b.step;
    	}
    };
    void prepare(int x,int y,char ch)
    {
    	char ch2;
    	int x2,y2;
    	if(ch=='D')
    	ch2='E',x2=e1,y2=e2;
    	else
    	ch2='D',x2=d1,y2=d2;
    	for(int i=x-1;i>=0;i--)
    	{
    		if(map[i][y]=='X'||i==x2&&y==y2)
    		break;
    		if(map[i][y]=='.')
    		map[i][y]=ch;
    		else if(map[i][y]==ch2)
    		map[i][y]='*';
    		else if(map[i][y]=='S')
    		{
    			map[i][y]=ch;
    			break;
    		}
    	}
    	for(int i=x+1;i<n;i++)
    	{
    		if(map[i][y]=='X'||i==x2&&y==y2)
    		break;
    		if(map[i][y]=='.')
    		map[i][y]=ch;
    		else if(map[i][y]==ch2)
    		map[i][y]='*';
    		else if(map[i][y]=='S')
    		{
    			map[i][y]=ch;
    			break;
    		}
    	}
    	for(int i=y+1;i<m;i++)
    	{
    		if(map[x][i]=='X'||x==x2&&i==y2)
    		break;
    		if(map[x][i]=='.')
    		map[x][i]=ch;
    		else if(map[x][i]==ch2)
    		map[x][i]='*';
    		else if(map[x][i]=='S')
    		{
    			map[x][i]=ch;
    			break;
    		}
    	}
    	for(int i=y-1;i>=0;i--)
    	{
    		if(map[x][i]=='X'||x==x2&&i==y2)
    		break;
    		if(map[x][i]=='.')
    		map[x][i]=ch;
    		else if(map[x][i]==ch2)	
    		map[x][i]='*';
    		else if(map[x][i]=='S')
    		{
    			map[x][i]=ch;
    			break;
    		}
    	}
    }
    bool limit(int x,int y)
    {
    	if(x==d1&&y==d2)
    	return false;
    	if(x==e1&&y==e2)
    	return false;
    	if(x<0||y<0||x>=n||y>=m||map[x][y]=='X')
    	return false;
    	return true;
    }
    void check_result(node &temp1)
    {
    	int x=temp1.x;
    	int y=temp1.y;
    	if(map[x][y]=='D')
    	temp1.isfindD=true;
    	else if(map[x][y]=='E')
    	temp1.isfindE=true;
    	else if(map[x][y]=='*')
    	temp1.isfindD=temp1.isfindE=true;
    }
    int bfs(int x1,int y1,int time)
    {
    	node temp1,temp2;
    	priority_queue<node>s;
    	while(!s.empty())
    	s.pop();
    	temp1.x=x1;temp1.y=y1;temp1.step=0;
    	temp1.isfindD=temp1.isfindE=false;
    	check_result(temp1);
    	visE[x1][y1]=temp1.isfindE;
    	visD[x1][y1]=temp1.isfindD;
    	vis[x1][y1]=true;
    	s.push(temp1);
    	while(!s.empty())
    	{
    		temp1=temp2=s.top();
    		s.pop();
    		if(temp1.step>time)
    		return -1;
    		if(temp1.isfindD&&temp1.isfindE)
    		return temp1.step; 
    		for(int i=0;i<4;i++)
    		{
    			int x1=temp1.x+dir[i][0];
    			int y1=temp1.y+dir[i][1];
    			if(limit(x1,y1)&&(!vis[x1][y1]||!(visE[x1][y1]==temp1.isfindE&&visD[x1][y1]==temp1.isfindD)))
    			{
    				temp1.x=x1;
    				temp1.y=y1;
    				temp1.step++;
    				check_result(temp1);
    				vis[x1][y1]=true;
    				visE[x1][y1]=temp1.isfindE;
    				visD[x1][y1]=temp1.isfindD;	
    				s.push(temp1);
    				temp1=temp2;
    			}
    		}
    	}
    	return -1;
    }
    int main()
    {
    	int ncase=1;
    	while(~scanf("%d %d %d",&n,&m,&t))
    	{
    		memset(map,0,sizeof(map));
    		for(int i=0;i<n;i++)
    		{
    			getchar();
    			for(int j=0;j<m;j++)
    			{
    				scanf("%c",&map[i][j]);
    				if(map[i][j]=='S')
    				{
    					s1=i;
    					s2=j;
    				}
    				if(map[i][j]=='D')
    				{
    					d1=i;
    					d2=j;
    				}
    				if(map[i][j]=='E')
    				{
    					e1=i;
    					e2=j;
    				}
    			}
    		}
    		prepare(d1,d2,'D');
    		prepare(e1,e2,'E');
    		memset(visD,false,sizeof(visD));
    		memset(visE,false,sizeof(visE));
    		memset(vis,false,sizeof(vis));
    		printf("Case %d:
    %d
    ",ncase++,bfs(s1,s2,t));
    	}
    }


  • 相关阅读:
    Windows下如何检测用户修改了系统时间并且把系统时间改回来
    洛谷 1220 关路灯
    洛谷 2279 [HNOI2003]消防局的设立
    洛谷 1498 南蛮图腾
    bzoj 1036 [ZJOI2008]树的统计Count 树链剖分模板
    codevs 1021 玛丽卡 SPFA
    codevs 1077 多源最短路 flyod
    Vijos P1133 装箱问题 01背包
    codevs 1069 关押罪犯 并查集
    codevs 1073 家族 并查集
  • 原文地址:https://www.cnblogs.com/llguanli/p/7133579.html
Copyright © 2020-2023  润新知