赦免战俘
题目背景
借助反作弊系统,一些在月赛有抄袭作弊行为的选手被抓出来了!
题目描述
现有 2 n × 2 n ( n ≤ 10 ) 2^n\times 2^n (n\le10) 2n×2n(n≤10) 名作弊者站成一个正方形方阵等候 kkksc03 的发落。kkksc03 决定赦免一些作弊者。他将正方形矩阵均分为 4 个更小的正方形矩阵,每个更小的矩阵的边长是原矩阵的一半。其中左上角那一个矩阵的所有作弊者都将得到赦免,剩下 3 个小矩阵中,每一个矩阵继续分为 4 个更小的矩阵,然后通过同样的方式赦免作弊者……直到矩阵无法再分下去为止。所有没有被赦免的作弊者都将被处以棕名处罚。
给出 n n n,请输出每名作弊者的命运,其中 0 代表被赦免,1 代表不被赦免。
输入格式
一个整数 n n n。
输出格式
2 n × 2 n 2^n \times 2^n 2n×2n 的 01 矩阵,代表每个人是否被赦免。数字之间有一个空格。
样例 #1
样例输入 #1
3
样例输出 #1
0 0 0 0 0 0 0 1
0 0 0 0 0 0 1 1
0 0 0 0 0 1 0 1
0 0 0 0 1 1 1 1
0 0 0 1 0 0 0 1
0 0 1 1 0 0 1 1
0 1 0 1 0 1 0 1
1 1 1 1 1 1 1 1
思路
将矩阵不断分成4个象限,将第二象限的所有元素标记为0,直到无法继续分割。
AC代码
#include <iostream>
#include <cstring>
#include <cmath>
#define AUTHOR "HEX9CF"
using namespace std;
const int maxn = 1200;
int n, m;
bool a[maxn][maxn];
void f(int x1, int x2, int y1, int y2)
{
if (x2 - x1 < 1 || y2 - y1 < 1)
{
return;
}
int midX = (x1 + x2 - 1) / 2;
int midY = (y1 + y2 - 1) / 2;
for (int i = x1; i <= midX; i++)
{
for (int j = y1; j <= midY; j++)
{
a[i][j] = 0;
}
}
f(x1, midX, y1, midY); // 2
f(midX + 1, x2, y1, midY); // 1
f(x1, midX, midY + 1, y2); // 3
f(midX + 1, x2, midY + 1, y2); // 4
}
void print(int m)
{
for (int i = 1; i <= m; i++)
{
for (int j = 1; j <= m; j++)
{
if (j != 1)
{
putchar(' ');
}
putchar('0' + (int)a[i][j]);
}
putchar('\n');
}
}
int main()
{
memset(a, 1, sizeof(a));
cin >> n;
m = pow(2, n);
f(1, m, 1, m);
print(m);
return 0;
}