题目:

师傅又被妖怪抓走了

时间限制: 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
上传者
ACM_张希鹏

思路:

今天比赛的时候遇到了一道广搜题,和这个类似,今天我们做了四个小时,愣是没做出来,最后听学长说这题要用到状态压缩,就来做做这个题。。

首先根据题意,只要看见八戒和唐僧就行了,那就意味着只要这个坐标和唐僧八戒同时有交叉,那就证明已经发现了他们。所以我们先对这个地图做一个预处理

在不碰到墙壁的情况下,把D所在的行和列中所有的字符都变成d,当遇到墙壁时停下。把E所在的行和列中左右的字符变成e,当遇到墙壁的时候停下。当e和d相遇的时候,就把这个坐标变成y,来表示这个点是交叉点

具体看下图,根据样例把地图变成的样子如图所示:

这样就容易理解多了。

在存图的时候把起始点的坐标记录下来,在预处理完毕后,以这个点来进行广搜,需要注意的是这里用到状态压缩,定义

dp[i][j][st],如果搜到d,把状态变成vis[i][j][1],搜到e变成vis[i][j][2],搜到y变成vis[i][j][3],这样可以把状态标记了,省时间,具体看注释

代码:

#include <cstdio>
#include <cstring>
#include <cctype>
#include <string>
#include <set>
#include <iostream>
#include <stack>
#include <queue>
#include <vector>
#include <algorithm>
#define mem(a,b) memset(a,b,sizeof(a))
#define inf 0x3f3f3f3f
#define mod 10000007
#define debug() puts("what the fuck!!!")
#define N 1001000
#define M 1000000
#define ll long long
using namespace std;
int n,m,t,ans;
char map[120][120];
int vis[120][120][4];
int go[4][2]= {0,1,0,-1,1,0,-1,0};
struct node
{int x,y,step,st;
};
int check(int x,int y)
{if(map[x][y]=='X'||map[x][y]=='D'||map[x][y]=='E')return 0;return 1;
}
char solve(int chr,int op)
{if(op==1&&chr=='e'||op==0&&chr=='d')//如果两个有交点,那么返回'y'return 'y';return op?'d':'e';//判断状态,状态为0时把所在得点变为'e',为1时把状态变成'd'
}
void update(int x,int y,int ok)//更新各个点的字符,目的是把D所在的行和列全部更新成d,把E所在的行和列全部更新成e,如果这两个有交叉就用y来表示
{for(int i=x+1; i<m&&check(i,y); i++) //向右遍历,且不怕碰到墙或者D和Emap[i][y]=solve(map[i][y],ok);for(int i=x-1; i>=0&&check(i,y); i--) //向左map[i][y]=solve(map[i][y],ok);for(int i=y+1; i<n&&check(x,i); i++) //向下遍历,且不怕碰到墙或者D和Emap[x][i]=solve(map[x][i],ok);for(int i=y-1; i>=0&&check(x,i); i--) //向上map[x][i]=solve(map[x][i],ok);
}
int st_solve(char x,int st)//状态压缩
{if(x=='d') st|=1;if(x=='e') st|=2;if(x=='y') st|=3;return st;
}
void bfs(node s)
{s.step=0;s.st=st_solve(map[s.x][s.y],0);mem(vis,0);queue<node>q;q.push(s);vis[s.x][s.y][s.st]=1;while(!q.empty()){node now=q.front(),to;q.pop();if(now.st==3){ans=now.step;return;}for(int i=0; i<4; i++){to.x=now.x+go[i][0];to.y=now.y+go[i][1];to.step=now.step+1;to.st=now.st;if(check(to.x,to.y)&&vis[to.x][to.y][to.st]==0&&to.x>=0&&to.x<n&&to.y>=0&&to.y<=m)//没有标记过,不越界,且不是墙和D,E{to.st=st_solve(map[to.x][to.y],to.st);vis[to.x][to.y][to.st]=1;q.push(to);}}}
}
int main()
{int q=1;while(~scanf("%d%d%d",&n,&m,&t)){mem(map,0);node s;for(int i=0; i<n; i++){scanf("%s",map[i]);for(int j=0; j<m; j++){if(map[i][j]=='S'){s.x=i;s.y=j;}}}for(int i=0; i<n; i++){for(int j=0; j<m; j++){if(map[i][j]=='D')update(i,j,1);if(map[i][j]=='E')update(i,j,0);}}
//        puts("");
//        for(int i=0; i<n; i++,puts(""))
//            for(int j=0; j<m; j++)
//                printf("%c   ",map[i][j]);
//        puts("");ans=inf;bfs(s);printf("Case %d:\n",q++);if(ans>t)puts("-1");elseprintf("%d\n",ans);}return 0;
}

NYOJ999 师傅又被妖怪抓走了(预处理+状态压缩+广搜BFS)相关推荐

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

    题目999 题目信息 执行结果 本题排行 讨论区 师傅又被妖怪抓走了 时间限制:1000 ms | 内存限制:65535 KB 难度:3 描写叙述 话说唐僧复得了孙行者,师徒们一心同体,共诣西方.自宝 ...

  2. NYOJ999 师傅又被妖怪抓走了

    只记得当下的眼疼 , ok 各种数据也试了 , 就是 他娘的不对 , 我也是醉了 . 也是日了最野的狗 附上日了哮天犬的代码 , 这个题 先放放, 一段时间后再试试 , 明天开始状态压缩吧 .为期两天 ...

  3. nyoj-999 师傅又被妖怪抓走了

    http://acm.nyist.net/JudgeOnline/problem.php?pid=999 题解:   把师傅所在行和列标记为 1 状态   'd' 二师兄所在行和列标记为 2 状态   ...

  4. nyoj 999 师傅又被妖怪抓走了

    师傅又被妖怪抓走了 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描述 话说唐僧复得了孙行者,师徒们一心同体,共诣西方.自宝象国救了公主,承君臣送出城西,沿路饥餐渴饮,悟空便 ...

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

    题目:nyist 999 师傅又被妖怪抓走了 分析:在一个图中只要看到D点和E点就行的最小步数,看到的定义是:也就是说两个人在同一行或者同一列,并且中间没有障碍物或者没有其他人就可以看到对方. 所以可 ...

  6. NYOJ 师傅又被妖怪抓走了 双向BFS

    师傅又被妖怪抓走了 时间限制: 1000 ms  |  内存限制: 65535 KB 难度: 3 描述 话说唐僧复得了孙行者,师徒们一心同体,共诣西方.自宝象国救了公主,承君臣送出城西,沿路饥餐渴饮, ...

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

    师傅又被妖怪抓走了 时间限制: 1000 ms  |  内存限制:65535 KB 难度: 3 描述 话说唐僧复得了孙行者,师徒们一心同体,共诣西方.自宝象国救了公主,承君臣送出城西,沿路饥餐渴饮,悟 ...

  8. 可重复广搜 —— NYOJ 999 师傅又被妖怪抓走了

    对应 NYOJ 题目:点击打开链接 师傅又被妖怪抓走了 时间限制: 1000 ms  |  内存限制: 65535 KB 难度: 3 描述 话说唐僧复得了孙行者,师徒们一心同体,共诣西方.自宝象国救了 ...

  9. NYOJ 999 师傅又被妖怪抓走了(待续)

    题目链接 觉得自己现在的水平还是写不出这个程序的,网上说是预处理+双光搜+状态压缩,开始的时候我竟觉得是深搜,写着写着不对劲才发觉,当然预处理和双广搜和状态压缩都是第一次遇到,我还是先放一放,日后再来 ...

最新文章

  1. Ubuntu 18.04安装中文输入法
  2. Android Studio目录结构和Gradle构建Android项目
  3. .php on line 0,启动禅道项目管理软件时,报PHP Warning: PHP Startup: in Unknown on line 0解决方法...
  4. linux下ARP防御
  5. Magicodes.IE Csv导入导出
  6. 华为交换机命令_华为交换机常用命令
  7. MySQL入门之索引
  8. python导入mongodb_python实现mongodb的备份与导入
  9. 建设“智慧法院” 引入庭审语音识别系统
  10. 浅析Ruby on Rails部署方案(三)
  11. 笔记:复杂度分析(上)
  12. 360怎么看电脑配置_电脑配置清单速查表-AMD
  13. 大数据分析-第九章 知识图谱
  14. git bash粘贴快捷键
  15. OOC-用C实现面向对象
  16. Jenkins使用FTP上传文件报错问题处理
  17. 不错的学习金字塔模型
  18. 五常大米引入蚂蚁金服区块链,从大米“出生”就开始“验明正身”
  19. DirectX11 纹理采样
  20. shell-------数组遍历、切片、替换等操作

热门文章

  1. 机器学习算法(六):基于决策树的分类预测
  2. 新起点–记录我的每次成长
  3. 牛顿迭代法求平方根问题
  4. ZMQ — 基本使用与工具类
  5. 微信聊天功能测试用例
  6. 装完硬盘之后鼠标和界面变得很卡顿
  7. 优化方法(Tuning methodology)
  8. 如何把 linux 桌面变得像 Windows
  9. 服务器怎么清除网站数据,如何清理服务器数据库的废物啊是数据库有sql和access...
  10. 2023年武汉住建厅七大员怎么报名?报名流程?精准题库一次过??