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:\n%d\n",ncase++,bfs(s1,s2,t));
}
}
nyoj999 师傅又被妖怪抓走了 (预处理+bfs+状态压缩)的更多相关文章
- NYOJ999 师傅又被妖怪抓走了
只记得当下的眼疼 , ok 各种数据也试了 , 就是 他娘的不对 , 我也是醉了 . 也是日了最野的狗 附上日了哮天犬的代码 , 这个题 先放放, 一段时间后再试试 , 明天开始状态压缩吧 .为期两天 ...
- nyoj 999——师傅又被妖怪抓走了——————【双广搜】
师傅又被妖怪抓走了 时间限制:1000 ms | 内存限制:65535 KB 难度:3 描述 话说唐僧复得了孙行者,师徒们一心同体,共诣西方.自宝象国救了公主,承君臣送出城西,沿路饥餐渴饮,悟 ...
- uva 1601 poj 3523 Morning after holloween 万圣节后的早晨 (经典搜索,双向bfs+预处理优化+状态压缩位运算)
这题数据大容易TLE 优化:预处理, 可以先枚举出5^3的状态然后判断合不合法,但是由于题目说了有很多墙壁,实际上没有那么多要转移的状态那么可以把底图抽出来,然后3个ghost在上面跑到时候就不必判断 ...
- openjudge 大师兄,师傅被妖怪抓走啦
描述 孙悟空听到沙僧大喊一句:“大师兄,师傅被妖怪抓走啦!”于是孙悟空直追白骨精而去.孙悟空在一条长度为L的森林小路上飞奔,上面有L+1个整点,依次为0,1,2……L.白骨精会使用一种大范围的攻击法术 ...
- shu_1548 悟空问题(大哥,主妖怪抓走的朋友!)
http://202.121.199.212/JudgeOnline/problem.php?cid=1078&pid=17 分析: 直接暴力了.. . 代码: #include <s ...
- Light OJ 1037 - Agent 47(预处理状态压缩DP)
题目大意: 有个特工要执行任务,他会遭遇到最多15个目标,特工必须把他们全部杀死.当他杀死一个目标后他可以使用目标的武器来杀死其他人.因此他必须有一个杀人的顺序,使得他开枪的次数最小. 现在给你一个表 ...
- poj3669 Meteor Shower(预处理+bfs)
https://vjudge.net/problem/POJ-3669 先给地图a[][]预处理每个位置被砸的最小时间.然后再bfs. 纯bfs,还被cin卡了下时间.. #include<io ...
- 【HDOJ3567】【预处理bfs+映射+康拓展开hash】
http://acm.hdu.edu.cn/showproblem.php?pid=3567 Eight II Time Limit: 4000/2000 MS (Java/Others) Me ...
- 【NOIP2013】 华容道 bfs预处理+bfs
这一题我们考虑一个最裸的算法: 我们设$dp[i][j][k][l]$表示当前棋子在$(i,j)$且空格在$(k,l)$时的最小步数 然后显然随便转移一下就好了,时间复杂度为$O(q(nm)^2)$. ...
随机推荐
- @Accessors
@Accessors 作用:存取器,用于配置getter和setter方法的生成结果 三个属性:fluent.chain.prefix 1.fluent:流畅的,设置为true,getter和sett ...
- poj2486--Apple Tree(树状dp)
Apple Tree Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 7789 Accepted: 2606 Descri ...
- 4.2.2 MINUS
4.2.2 MINUS正在更新内容,请稍后
- DataTable填充实体类返回泛型集合
昨天找坤哥看到我的一段代码.例如以下: 略微解释下,这段代码时D层查询结束后,将datatable查询到的结果赋值给实体对象的属性,然后返回实体的过程.坤哥看了之后问我.假设实体有500多个属性.难道 ...
- hdu1533Going Home KM算法
//给一个n*m的图, //m表示人,h表示房子 //问全部人走回家的最小步数 //每一个人仅仅能进一间房 //非常明显的最大带权匹配 //每一个人到每每间房的距离即为权值 //因为是求最小,仅仅要改 ...
- C++模板类代码只能写在头文件?
这个问题,实际上我几年前就遇到了.最近写个模板类玩的时候,再次遇到. 当我非常仔细的将定义和实现分开,在头文件中保留了最少的依赖后,一切就绪.cpp单独编过.但是当使用的时候,就会报告所有的函 ...
- 如何解决Linux下的软件包依赖问题
650) this.width=650;" border="0" alt="" src="http://img1.51cto.com/att ...
- java种instanceof方法和getclass方法的区别
在比较一个类是否和另一个类属于同一个类实例的时候,我们通常可以采用instanceof和getClass两种方法通过两者是否相等来判断,但是两者在判断上面是有差别的,下面写个测试类. public c ...
- C_数组详解
数组: 一 一维数组 1.1 一维数组的定义: 类型符 数组名[常量表达式]; int a[10]; 说明: 1.数组的命名规则遵循标识符命名规则. 2.定义时需要指定元素的个数.方括号里的常量表达式 ...
- BZOJ3511: 土地划分(最小割)
Description Y国有N座城市,并且有M条双向公路将这些城市连接起来,并且任意两个城市至少有一条路径可以互达. Y国的国王去世之后,他的两个儿子A和B都想成为新的国王,但他们都想让这个国家更加 ...