2019第十届蓝桥杯国赛C组C/C++第I题 胖子走迷宫
这次C组的题目突然比以前加大了难度,但如果想明白了,其实还是特别简单。
这道题当时卡了我将近两个小时,一直处于放弃和不放弃的边缘,最终心态爆炸,间接地让我没拿到一等奖。
当天吃完饭就和老师同学们一起逛长安街,放空了心态,一直到了晚上,回来洗了个澡,始终睡不着,突然听同房的同学一句话,顿时醒悟,然后尝试做了一下,居然做出来了。
总而言之,还是训练少了,拿到新题目,总会有束手无策之感,希望第二次来北京的时候,可以上领奖台。
题目简介
有一个n*m的迷宫(可能原题是边长为n的正方形迷宫,但我记不太清了,都差不多),+为平地*为墙(我做的时候没想起来,用0代表空地,1代表了墙,一个意思),有一个大胖子,在时间单位为0的时候,占5×5的方格,每次时间单位都可以选择停顿和走一步,给定一个正整数k,在第k时间单位结束的那一刻,胖子会变瘦,占3×3的方格,在第2k时间单位结束的那一刻,胖子再次变瘦,变成只占1×1方格。起始点为(3,3),结束点为(n-2,m-2)。问走出迷宫最短要多长时间。
输入
第一行三个正整数n,m,k,表示迷宫的长,高和k
后面n行每行m个字符,代表迷宫的状态
输出
一个整数,表示最短要多长时间。
测试用例
输入:
9 9 5
000000000
000000000
000000000
000000000
000000000
111011111
000000000
000000000
000000000
输出:
16
想明白了其实很简单,条件BFS,
普通BFS上,加入时间限制,根据时间判断有多胖,
再在每次循环取出节点,进行上下左右遍历之前(之后也行),将节点本身放入队列,代表站着不动
就这样就OK了,注意好各种细节就OK,下面是代码
如果有兴趣的话,还可以做出优化,比如2k时间之后不再加入站着不动的情况、优化胖形态的能否行走判断等等
#include <iostream>
#include <queue>
using namespace std;
int n, m;
int k;
//用于记录
char maze[3010][3010];
bool vis[3010][3010] = { 0 };
//记录第i*k个时间点有多胖,不放心的话,这个数组可以开大一点
int fat_record[100000] = { 2, 1, 0 };
//用于移动
int move_x[4] = { -1,1,0,0 };
int move_y[4] = { 0,0,-1,1 };
//节点记录纵横坐标和该节点的时间
struct node
{
int x;
int y;
int time;
};
void bfs()
{
//一个装节点的队列,用于bfs
queue<node> que;
//将初始节点放入队列
vis[3][3] = true;
que.push({ 3, 3, 0 });
//开始bfs
while (!que.empty())
{
node temp = que.front();
que.pop();
//当前节点的位置满足条件,则输出当前节点中记录的位置
if (temp.x == n - 2 && temp.y == m - 2)
{
cout << temp.time << endl;
break;
}
//直接将站着不动的情况放入队列
que.push({ temp.x, temp.y, temp.time + 1 });
//往四个方向枚举
for (int i = 0; i < 4; i++)
{
int cachex = temp.x + move_x[i];
int cachey = temp.y + move_y[i];
int fat = fat_record[(temp.time) / k];
//判断是否访问过
if (vis[cachex][cachey] != false)
continue;
//是否出边界
if (1 > cachex - fat || cachex + fat > n || 1 > cachey - fat || cachey + fat > n)
continue;
//计算是否能走到下一个格子
int flag = false;
if (fat != 0)
{
for (int i = cachex - fat; i <= cachex + fat; i++)
{
for (int j = cachey - fat; j <= cachey + fat; j++)
{
if (maze[i][j] != '0')
flag = true;
}
}
}
else
{
if (maze[cachex][cachey] != '0')
flag = true;
}
if (flag != false)
continue;
//放入节点
vis[cachex][cachey] = true;
que.push({ cachex, cachey, temp.time + 1 });
}
}
}
int main()
{
cin >> n >> m >> k;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
cin >> maze[i][j];
bfs();
return 0;
}