变色球在矩阵中的运动

题目描述:

小明是一个放置类游戏爱好者,他只要盯着某些东西的运动过程,就能获得放松与舒适。所以小明的一个癖好就是盯着他的电脑的屏幕保护程序动画观看。小明的屏幕保护程序动画是这样的,屏幕上会出现一个 n 行 m 列的方格矩阵,其中有两类格子,黑色的格子叫做空地,白色的格子叫做墙,矩阵周围的一圈都是墙(即第一行、第一列、第 n 行、第 m 列都是墙,其余的地方为空地)。然后屏幕保护程序出现的时候,会随机在一个空地上出现一个带颜色的格子叫做小球(会是红绿蓝三种颜色其中一种),随后,这个格子会随机一个方向(左上,右上,右下,左下四个方向其中之一)每秒移动一格。当颜色格子碰到墙时,其碰到墙方向的运动矢量会反向,同时自己格子的颜色会变化(变成红绿蓝其中一种,且必定与原颜色不同)。

小明就是能盯着这个小球来回弹跳变色能看一下午。某天小明看得正开心的时候突然想上厕所,他记住了格子矩阵的状态和小球当前状态,他想知道从自己离开座位到上厕所回来后这段时间里,小球的颜色变化了多少次。

输入描述
每个输入数据包含多个测试点。
第一行为测试点的个数 Q(Q <= 5)。

对于每个测试点,第一行为两个整数 N,M(0 < N <= 200,0 < M <= 200),分别表示格子矩阵有 N 行 M 列。同时这个矩阵,是以第一行在上方,第 N 行在下方,第一列在左边,第 M 列在右边的样例显示在小明面前的。

接下来的一行,四个整数 X(3 <= X <= N-2), Y(3 <= Y <= M-2), W(0 <= W <= 3), T(0 < T < 1000)。X、Y 表示初始化时(第 0 秒)小球处于 X 行 Y 列的格子上,W 表示小球初始的运动方向,0 表示左上方,1 表示右上方,2 表示右下方,3 表示左下方。T 表示小明离开座位到上完厕所回来需要 T 秒。
输出描述
对于每个测试点,输出一行,该行包含一个整数 C,表示 T 秒内(即 1 秒到 T 秒之间)小球的颜色变化了 C 次。

Example 1:

Input:
5
6 5
4 3 0 42
10 6
5 3 1 46
5 5
3 3 1 7
5 5
3 3 1 6
7 7
4 5 2 9
Output:
35
22
8
6
5

说明
对于一个 7*5 大小的屏幕。
第 0 秒时,屏幕的区块状态为:(其中2表示小球,小球运动方向为左下)
1 1 1 1 1
1 0 0 0 1
1 0 2 0 1
1 0 0 0 1
1 0 0 0 1
1 0 0 0 1
1 1 1 1 1
第 1 秒时,屏幕的区块状态为:小球碰到左侧的墙,所以水平方向上运动动量反向,竖直方向上的运动动量不变,所以运动方向变为右下。同时由于碰到了砖块,其颜色发生了变化。
1 1 1 1 1
1 0 0 0 1
1 0 0 0 1
1 3 0 0 1
1 0 0 0 1
1 0 0 0 1
1 1 1 1 1
第 2 秒时,屏幕的区块状态为:(其中3表示小球,小球运动方向为右下)
1 1 1 1 1
1 0 0 0 1
1 0 0 0 1
1 0 0 0 1
1 0 3 0 1
1 0 0 0 1
1 1 1 1 1

问题分析

以输入
10 6
5 3 1 46
为例进行分析。

x, y 表示此时小球所在行和列,w1, w2 表示小球此时在行,列上的运动方向,比如w1=-1,w2=1表示向矩阵右上方运动。当行的位置 x==1 或者 x==n-2 时,需要将行运动方向 w1 反向;当列的位置 y==1 或者 y==m-2 时,需要将行运动方向 w2 反向。

每次在行运动方向上反向一次,或者在列运动方向上反向一次,球需要变色一次。

在这里插入图片描述

#include<iostream>
#include<vector>
using namespace std;

int n, m;
int dir[4][2] = { { -1, -1 }, { -1, 1 }, { 1, 1 }, { 1, -1 } };

int dirw1(int x,int y,int w1)
{
	int tmp = w1;
	if (x == 1 || x == n - 2)
		tmp = -w1;
	return tmp;
}

int dirw2(int x, int y, int w2)
{
	int tmp = w2;
	if (y == 1 || y == m - 2)
		tmp = -w2;
	return tmp;
}

int change(int x,int y)
{
	int count = 0;
	if (x == 1 || x == n - 2)
		count++;
	if (y == 1 || y == m - 2)
		count++;
	return count;
}

int numchange(vector<vector<int>>vec, int x, int y, int w, int t)
{
	int su = 0;
	int w1=dir[w][0], w2=dir[w][1];
	while (t)
	{
		x = x + w1; y = y + w2;
		int tmp = change(x, y);
		if (tmp)
		{
			su = su + tmp;
			w1 = dirw1(x, y, w1);
			w2 = dirw2(x, y, w2);
		}
		t--;
	}
	return su;
}

int main()
{
	int Q;
	cin >> Q;
	while (Q--)
	{
		cin >> n >> m;
		vector<vector<int>>vec(n, vector<int>(m, 0));
		for (int i = 0; i < n; i++)
		{
			vec[i][0] = 1;
			vec[i][m - 1] = 1;
		}
		for (int i = 0; i < m; i++)
		{
			vec[0][i] = 1;
			vec[n - 1][i] = 1;
		}
		int x, y, w, t;
		cin >> x >> y >> w >> t;
		cout << numchange(vec, x - 1, y - 1, w, t) << endl;
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值