问候一下~
Hello,大家好,我是Zac(经典开场白)。今天我又来给大家一点灵感了(没事可干可以写写文章啥的),上期我可是有23个小👍🏼👍🏼,所以我又要写文章了。
传送一下:here
题目背景
借助反作弊系统,一些在月赛有抄袭作弊行为的选手被抓出来了!
题目描述
现有 2^n×2^n(n≤10) 名作弊者站成一个正方形方阵等候 黑暗造物主-Zac 的发落。黑暗造物主-Zac 决定赦免一些作弊者。他将正方形矩阵均分为 4 个更小的正方形矩阵,每个更小的矩阵的边长是原矩阵的一半。其中左上角那一个矩阵的所有作弊者都将得到赦免,剩下 3 个小矩阵中,每一个矩阵继续分为 4 个更小的矩阵,然后通过同样的方式赦免作弊者……直到矩阵无法再分下去为止。所有没有被赦免的作弊者都将被处以棕名处罚。
给出 n,请输出每名作弊者的命运,其中 0 代表被赦免,1 代表不被赦免。
输入格式
一个整数 n。
输出格式
2^n×2^n 的 01 矩阵,代表每个人是否被赦免。数字之间有一个空格。
输入输出样例
输入 #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
题目分析:
这道题其实很简单,以下是需要注意的方面:
递归函数:
我们需要一个函数,用来进行递归操作。每次在函数里再次执行3个函数,用来模拟分成的子图形:
int ans[1050][1050] = {0}, n;
void she(int x, int y, int n) {
if (n == 0) {
ans[x][y] = 1;
} else {
she(x + (pow(2, n - 1)), y, n - 1);
she(x, y + (pow(2, n - 1)), n - 1);
she(x + (pow(2, n - 1)), y + (pow(2, n - 1)), n - 1);
}
}
最后,main函数就不用我说了:
主函数:
int main() {
cin >> n;
she(0, 0, n);
for (int i = 0; i < pow(2, n); i++) {
for (int j = 0; j < pow(2, n); j++) {
cout << ans[i][j] << " ";
}
cout << endl;
}
return 0;
}
接下来看一下AC代码吧:
AC代码:
强迫症版:
#include <iostream>
#include <cmath>
using namespace std;
int ans[1050][1050] = {0}, n;
void she(int x, int y, int n) {
if (n == 0) {
ans[x][y] = 1;
} else {
she(x + (pow(2, n - 1)), y, n - 1);
she(x, y + (pow(2, n - 1)), n - 1);
she(x + (pow(2, n - 1)), y + (pow(2, n - 1)), n - 1);
}
}
int main() {
cin >> n;
she(0, 0, n);
for (int i = 0; i < pow(2, n); i++) {
for (int j = 0; j < pow(2, n); j++) {
cout << ans[i][j] << " ";
}
cout << endl;
}
return 0;
}
懒人版(通常都会加一下哈):
#include<iostream>
#include<cmath>
using namespace std;
int ans[1050][1050]={0},n;
void she(int x,int y,int n){
if(n==0)ans[x][y]=1;
else{
she(x+pow(2,n-1),y,n-1);
she(x,y+pow(2,n-1),n-1);
she(x+pow(2,n-1),y+pow(2,n-1),n-1);
}
}
int main(){
cin>>n;
she(0,0,n);
for(int i=0;i<pow(2,n);i++){
for(int j=0;j<pow(2,n);j++){
cout<<ans[i][j]<<" ";
}
cout<<endl;
}
return 0;
}
代码分析:
逐行解释
这段代码用于解决一个特定的问题:在一个 2 ^ n * 2 ^ n 的矩阵中,按照特定的规则赦免一些元素(在这个上下文中,元素代表作弊者)。下面是代码的逐行解释:
1. `#include <iostream>` 和 `#include <cmath>`:这两行代码包含了标准输入输出流库和数学库,分别用于处理输入输出和数学运算。
2. `using namespace std;`:这行代码允许我们直接使用标准命名空间(std)中的名称,而不需要前缀 `std::`。
3. `int ans[1050][1050] = {0}, n;`:这行代码声明了一个二维数组 `ans`,用于存储矩阵的值,以及一个整数 `n`,用于存储矩阵的阶数。数组 `ans` 的所有元素初始化为0。
4. `void she(int x, int y, int n) {`:这是一个递归函数,用于处理矩阵。它接受三个参数:`x` 和 `y` 表示当前处理的子矩阵的左上角坐标,`n` 表示当前子矩阵的阶数。
5. `if (n == 0) { ans[x][y] = 1; }`:这是递归的终止条件。如果 `n` 为0,意味着当前子矩阵只有一个元素,这个元素将被设置为1(不被赦免)。
6. `else {`:如果不是递归的终止条件,执行以下递归调用:
- `she(x + (pow(2, n - 1)), y, n - 1);`:递归调用函数,处理右上角的子矩阵。
- `she(x, y + (pow(2, n - 1)), n - 1);`:递归调用函数,处理左下角的子矩阵。
- `she(x + (pow(2, n - 1)), y + (pow(2, n - 1)), n - 1);`:递归调用函数,处理右下角的子矩阵。
7. `int main() {`:这是程序的主函数。
8. `cin >> n;`:从标准输入读取一个整数 `n`。
9. `she(0, 0, n);`:调用 `she` 函数,从整个矩阵的左上角开始处理。
10. `for (int i = 0; i < pow(2, n); i++) {`:外层循环,遍历矩阵的每一行。
11. `for (int j = 0; j < pow(2, n); j++) {`:内层循环,遍历矩阵的每一列。
12. `cout << ans[i][j] << " ";`:输出当前元素的值,并在其后打印一个空格。
13. `cout << endl;`:每打印完一行后,输出一个换行符。
14. `return 0;`:程序正常结束。
整个程序的逻辑是,通过递归地分割矩阵,每次分割时赦免左上角的子矩阵,直到矩阵不能再分割。最终,矩阵中的每个元素都会被设置为0(赦免)或1(不被赦免),并输出这个矩阵。
程序的核心逻辑:
-
初始化矩阵:首先,创建一个 2 ^ n * 2 ^ n 的矩阵,并将所有元素初始化为1,表示所有作弊者默认不被赦免。
-
递归分割:使用递归函数
she
来分割矩阵。每次递归调用时,矩阵被分为四个更小的子矩阵。对于每个分割步骤:-
赦免左上角子矩阵:左上角的子矩阵中的所有作弊者都被赦免,即将这些位置的值设置为0。
-
递归处理其他子矩阵:对剩下的三个子矩阵继续进行分割和处理,直到子矩阵的大小减小到1为止。
-
-
输出结果:在递归处理完成后,矩阵中的每个元素都表示了一个作弊者的命运。程序遍历并输出矩阵,每个元素后跟一个空格,每行元素输出完毕后换行
致谢:
(每篇文章,我指《小杨的字典》那一期,都会来一句)
感谢kimi小助手帮我进行了懒人版的转换,是它的智能给予我了效率,让我能顺利发表这篇文章。
也感谢所有支持我的人,是你们的鼓励与支持推动我前进,让我有了更多的动力,谢谢!
(END……对了,话说一键三连不过分吧?👍🏼📂✅🙏🏼)