第一周刷题:
【题目描述】
李华有大小的格局n×n,每个单元格为蓝色或红色。他可以表演完全k操作。在每次操作中,他选择一个单元格并将其颜色从红色更改为蓝色或从蓝色更改为红色。每个单元格都可以根据需要多次选择。是否有可能使图案与其旋转相匹配180度?
【输入】
第一行包含单个整数t (1≤t≤100) — 测试用例的数量。
每个测试用例的第一行包含两个整数n,k (1≤n≤103,0≤K≤109) — 模式的大小和操作数。
下一个每个n行包含n整数一个 , ∈{0,1} 单元格的初始颜色,0对于蓝色和1为红色。
保证总和n在所有测试用例中不超过103
【输出】
对于每组输入,如果可以制作与其旋转匹配的图案,请打印“YES”完全应用后k的操作,否则为“NO”。
解题思路
这个题还是不难的,毕竟它直接遍历是不会时间超限的,可以将数组分为两半,在前面的第一个开始与后面的最后一个比较,遇到不同的情况就将计数器 sum++(代表将其中一块的颜色反转)。
但是还有一个坑,就是题目要求将步数 k 用完,此时还要考虑另一种情况,就是步数没有超过题目要求的大小,还要比较剩余步数是否是偶数,是偶数时,表示将任意一块颜色反转两次,且不会改变结果。
还有一个要考虑的是:如果这个数组的长度和宽度 n 是一个奇数,那么它最中心的那块颜色始终不影响反转的结果,这是一个要考虑的特例。
代码如下:
#include<iostream>
using namespace std;
int a[1003][1003];
int main() {
int t;
int n, m;
cin >> t;
while (t--) {
int sum = 0;
cin >> n >> m;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
cin >> a[i][j];
}
}
for (int i = 0; i < n / 2; i++) {
for (int j = 0; j < n ; j++) {
if (a[i][j] != a[n - i - 1][n - j - 1])
sum++;
}
}
if (n % 2 == 1)
{
for (int i = 0; i < n / 2; i++) {
if (a[n / 2 ][i] != a[n / 2 ][n - i - 1])
sum++;
}
}
if (sum>m )
cout << "NO" << endl;
else {
if (n % 2 == 0 && (m - sum) % 2 == 1)
cout << "NO" << endl;
else
cout << "YES" << endl;
}
}
}