wyh的吃鸡
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
最近吃鸡游戏非常火,你们wyh学长也在玩这款游戏,这款游戏有一个非常重要的过程,就是要跑到安全区内,否则就会中毒持续消耗血量,我们这个问题简化如下
假设地图为n*n的一个图,图中有且仅有一块X的联通快代表安全区域,有一个起点S代表缩圈的时候的起点,图中C代表的是车(保证车的数量小于等于100),标记为.的代表空地,可以任意通过,O代表障碍物不能通过。每次没有车的时候2s可以走一个格(只能走自己的上下左右4个方向),有车的话时间为1s走一个格
现在告诉你最多能坚持的时间为t秒,问你在t秒内(含t秒)能否从s点到达安全区域,能的话输出YES,并且输出最短时间,不能的话输出NO
输入描述:
输入第一行一个整数T(1<=T<=10)
接下来有T组测试数据,每组测试数据输入2个数n和k(1<=n<=100,1<=k<=10^9)
接下来n行,每行n个字符,代表对应的n*n的地图,每个字符都是上面的一种,并且保证只有一个起点,只有一块安全区域。
输出描述:
对于每组测试数据,先输出能否到达,能的话输出YES,然后换行输出最短时间,如果不能的话直接输出NO
示例1
输入
3
2 3
.X
S.
2 3
.X
SC
2 4
.X
S.
输出
NO
YES
3
YES
4
思路
方法1
今天看到题解了,发现其实两边bfs就可以过。
来源:官方题解
方法2
启发式搜索,建立一个优先队列。
估值函数为从起点到这一点的花费。
优先队列的规则为始终优先拓展估值函数值小的点。
然后vis标记数组注意并没有说不能重复走,因为存在可能到毒里面拿车之后再回来的情况。开一个三位数组来当标记数组。简单来说,走路不能重复走走路走过的地方,坐车不能重复走过坐车的地方,但是坐车可以重复走走路走过的地方,很奇怪的规则吧233.
不过这样子就是最优解。
坑点
我也是第一次遇到启发式搜索啊
其实这道题有最优搜索模式,就是官方题解的那两种,不是直接到,就是找到车之后再到,别的走法绝对会比这两种方法花费的多。
说白了还是自己太菜。
AC代码
#include<bits/stdc++.h>
using namespace std;
char Map[106][106];
int vis[106][106][2];
int n,m;
int f[4][2] = {{0,1},{1,0},{0,-1},{-1,0}};
typedef struct{
int x;int y;
int mod;
int ans;//估值函数
}poi;
struct cmp//比较规则,在队列里面由小到大排列。
{
bool operator()(poi a,poi b)
{
return a.ans > b.ans;
}
};
bool judge(int x,int y,int mode)
{
if(x>=0&&x<n&&y>=0&&y<n&&vis[x][y][mode]==-1&&Map[x][y] != 'O')
return true;
else return false;
}
int head(int x,int y)
{
memset(vis,-1,sizeof(vis));
poi start;
vis[x][y][0] = 1;
start.x = x;
start.y = y;
start.mod = 0;
start.ans = 0;
priority_queue<poi,vector<poi>,cmp > q;
q.push(start);
while(!q.empty())
{
poi then;
then = q.top();
q.pop();
if(then.ans > m) return 0x3f3f3f3f;
if(Map[then.x][then.y]=='X'){
return then.ans;
}
for(int i = 0 ; i < 4; i++)
{
poi next;
next.x = then.x+f[i][0];
next.y = then.y+f[i][1];
int tempmod;
if(then.mod){
tempmod = 1;
}
else tempmod = 0;
if(judge(next.x,next.y,tempmod)){
/*换车操作*/
if(Map[next.x][next.y]=='C'){
next.mod = 1;
}
else next.mod = then.mod;
if(then.mod){
next.ans = then.ans+1;
}
else next.ans = then.ans+2;
/*标记换车操作*/
if(next.mod){
vis[next.x][next.y][1] = 1;
}
else vis[next.x][next.y][0] = 1;
if(next.ans <= m) //这一个if可以不要。
q.push(next);
}
}
}
return 0x3f3f3f3f;
}
void solve(void)
{
int t;
cin>>t;
while(t--)
{
cin>>n>>m;
for(int i = 0 ; i < n ; i++){
cin>>Map[i];
}
int startx,starty;
for(int i = 0 ; i < n ; i++){
for(int j = 0 ; j < n ; j++){
if(Map[i][j]=='S'){
startx = i;
starty = j;
goto mark;
}
}
}
mark:;
int anst = head(startx,starty);
if(anst<=m){
cout<<"YES"<<endl;
cout<<anst<<endl;
}
else cout<<"NO"<<endl;
}
}
int main(void)
{
solve();
return 0;
}