题目概述
小明准备给一个M行N列的地图染色,已知每个格子初始是白色(W),小明选择部分染成红色(R)。
染色的方法如下:
小明最开始站在地图的左上角,然后向下直走,将他经过的格子染成红色。
当他遇到以下情况之一,选择左转:
1.他走到了地图边界,无法直走;
2. 他前方的前方的格子为红色,为避免无法辨别路径,会左转。
当他遇到以下情况之一,会停下来:
1.他往前走的话会出现一个2*2的区域,该区域上的4个格子都是红色,这样会导致无法辨别路径,这时他停下来;
2. 他左转后无法直走只能继续左转,这时也停下来。
样例一:
输入:
4 4
输出:
RWRR
RWWR
RWWR
RRRR
说明:
小明从(1, 1)出发,最终走到(1, 3)。如果他直走会导致形成一个2*2的红色区域,因此会停下来。
样例二:
输入:
5 5
输出:
RWRRR
RWRWR
RWRWR
RWWWR
RRRRR
说明:
小明从(1, 1)出发,最终停在(3, 3)。当小明左转后由于无法直走到(3, 4),因此会停下来。
解题思路
这道题是经典的C++回型矩阵题目的变形。一种思路是直接用回型矩阵的方法来做(就是维护一个点,每次走到边界就转弯),不过要加一下额外的判断条件。
由于上面提到的解法调试起来比较麻烦_(:з」∠)_我尝试着先观察这个输出的矩阵:
试着统计一下,每次矩阵在一行/一列所走的最远距离,可以发现如下的结果:
行列的序号 | 经过的距离 |
1 | M |
2 | N-1 |
3 | M-1 |
4 | N-3 |
5 | M-3 |
6 | N-5 |
... | ... |
也就是说,我们可以把回型矩阵的实现中,用于判断走到哪一步转弯的条件,改成控制它的距离!只要经过的距离非负,小明就能一直移动。
代码示例
#include<iostream>
#include<math.h>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
int main()
{
int M, N;
cin >> M >> N;
int **val = new int *[M];
for (int i = 0; i < M; ++i)
{
val[i] = new int[N];
for (int j = 0; j < N; ++j)
val[i][j] = 0;
}
bool down_up = 1, right_left = 1;
int turns = 0;
int Ri = M - 1, Ci = N - 1;
for (int i = 0; i < M; ++i)
val[i][0] = 1;
int ri = M - 1, ci = 0;
while (Ri >= 0 && Ci >= 0 && Ri + Ci > 0)
{
if (turns % 2 == 0)
{
if (right_left == 1)
{
for (int ts = 0; ts < Ci; ++ts)
{
ci++;
val[ri][ci] = 1;
}
}
else
{
for (int ts = 0; ts < Ci; ++ts)
{
ci--;
val[ri][ci] = 1;
}
}
right_left = 1 - right_left;
Ci -= 2;
}
else
{
if (down_up == 1)
{
for (int ts = 0; ts < Ri; ++ts)
{
ri--;
val[ri][ci] = 1;
}
}
else
{
for (int ts = 0; ts < Ri; ++ts)
{
ri++;
val[ri][ci] = 1;
}
}
down_up = 1 - down_up;
Ri -= 2;
}
turns++;
}
for (int i = 0; i < M; ++i)
{
for (int j = 0; j < N; ++j)
{
if (val[i][j] == 0)
cout << "W";
else
cout << "R";
}
cout << endl;
}
return 0;
}