2021ALI算法0428笔试题之一:走格子

题目概述

小明准备给一个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++回型矩阵题目的变形。一种思路是直接用回型矩阵的方法来做(就是维护一个点,每次走到边界就转弯),不过要加一下额外的判断条件。

由于上面提到的解法调试起来比较麻烦_(:з」∠)_我尝试着先观察这个输出的矩阵:

试着统计一下,每次矩阵在一行/一列所走的最远距离,可以发现如下的结果:

行列的序号经过的距离
1M
2N-1
3M-1
4N-3
5M-3
6N-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;
}

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值