NYOJ999 师傅又被妖怪抓走了(预处理+状态压缩+广搜BFS)
题目:
师傅又被妖怪抓走了
- 描述
-
话说唐僧复得了孙行者,师徒们一心同体,共诣西方。自宝象国救了公主,承君臣送出城西,沿路饥餐渴饮,悟空便为师傅去化斋,等悟空回来,悟净慌慌张张的对悟空说:“不好了,不好了”,还没等悟净说完,悟空说:“师傅又被妖怪抓走了”,悟净:“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)相关推荐
- nyoj999 师傅又被妖怪抓走了 (预处理+bfs+状态压缩)
题目999 题目信息 执行结果 本题排行 讨论区 师傅又被妖怪抓走了 时间限制:1000 ms | 内存限制:65535 KB 难度:3 描写叙述 话说唐僧复得了孙行者,师徒们一心同体,共诣西方.自宝 ...
- NYOJ999 师傅又被妖怪抓走了
只记得当下的眼疼 , ok 各种数据也试了 , 就是 他娘的不对 , 我也是醉了 . 也是日了最野的狗 附上日了哮天犬的代码 , 这个题 先放放, 一段时间后再试试 , 明天开始状态压缩吧 .为期两天 ...
- nyoj-999 师傅又被妖怪抓走了
http://acm.nyist.net/JudgeOnline/problem.php?pid=999 题解: 把师傅所在行和列标记为 1 状态 'd' 二师兄所在行和列标记为 2 状态 ...
- nyoj 999 师傅又被妖怪抓走了
师傅又被妖怪抓走了 时间限制:1000 ms | 内存限制:65535 KB 难度:3 描述 话说唐僧复得了孙行者,师徒们一心同体,共诣西方.自宝象国救了公主,承君臣送出城西,沿路饥餐渴饮,悟空便 ...
- nyist 999 师傅又被妖怪抓走了 【双广搜 || BFS +状态压缩】
题目:nyist 999 师傅又被妖怪抓走了 分析:在一个图中只要看到D点和E点就行的最小步数,看到的定义是:也就是说两个人在同一行或者同一列,并且中间没有障碍物或者没有其他人就可以看到对方. 所以可 ...
- NYOJ 师傅又被妖怪抓走了 双向BFS
师傅又被妖怪抓走了 时间限制: 1000 ms | 内存限制: 65535 KB 难度: 3 描述 话说唐僧复得了孙行者,师徒们一心同体,共诣西方.自宝象国救了公主,承君臣送出城西,沿路饥餐渴饮, ...
- nyoj 999——师傅又被妖怪抓走了——————【双广搜】
师傅又被妖怪抓走了 时间限制: 1000 ms | 内存限制:65535 KB 难度: 3 描述 话说唐僧复得了孙行者,师徒们一心同体,共诣西方.自宝象国救了公主,承君臣送出城西,沿路饥餐渴饮,悟 ...
- 可重复广搜 —— NYOJ 999 师傅又被妖怪抓走了
对应 NYOJ 题目:点击打开链接 师傅又被妖怪抓走了 时间限制: 1000 ms | 内存限制: 65535 KB 难度: 3 描述 话说唐僧复得了孙行者,师徒们一心同体,共诣西方.自宝象国救了 ...
- NYOJ 999 师傅又被妖怪抓走了(待续)
题目链接 觉得自己现在的水平还是写不出这个程序的,网上说是预处理+双光搜+状态压缩,开始的时候我竟觉得是深搜,写着写着不对劲才发觉,当然预处理和双广搜和状态压缩都是第一次遇到,我还是先放一放,日后再来 ...
最新文章
- Ubuntu 18.04安装中文输入法
- Android Studio目录结构和Gradle构建Android项目
- .php on line 0,启动禅道项目管理软件时,报PHP Warning: PHP Startup: in Unknown on line 0解决方法...
- linux下ARP防御
- Magicodes.IE Csv导入导出
- 华为交换机命令_华为交换机常用命令
- MySQL入门之索引
- python导入mongodb_python实现mongodb的备份与导入
- 建设“智慧法院” 引入庭审语音识别系统
- 浅析Ruby on Rails部署方案(三)
- 笔记:复杂度分析(上)
- 360怎么看电脑配置_电脑配置清单速查表-AMD
- 大数据分析-第九章 知识图谱
- git bash粘贴快捷键
- OOC-用C实现面向对象
- Jenkins使用FTP上传文件报错问题处理
- 不错的学习金字塔模型
- 五常大米引入蚂蚁金服区块链,从大米“出生”就开始“验明正身”
- DirectX11 纹理采样
- shell-------数组遍历、切片、替换等操作