《赦免战俘》题解

问候一下~

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(不被赦免),并输出这个矩阵。

程序的核心逻辑:

  1. 初始化矩阵:首先,创建一个 2 ^ n * 2 ^ n 的矩阵,并将所有元素初始化为1,表示所有作弊者默认不被赦免。

  2. 递归分割:使用递归函数 she 来分割矩阵。每次递归调用时,矩阵被分为四个更小的子矩阵。对于每个分割步骤:

    • 赦免左上角子矩阵:左上角的子矩阵中的所有作弊者都被赦免,即将这些位置的值设置为0。

    • 递归处理其他子矩阵:对剩下的三个子矩阵继续进行分割和处理,直到子矩阵的大小减小到1为止。

  3. 输出结果:在递归处理完成后,矩阵中的每个元素都表示了一个作弊者的命运。程序遍历并输出矩阵,每个元素后跟一个空格,每行元素输出完毕后换行

致谢:

(每篇文章,我指《小杨的字典》那一期,都会来一句)

感谢kimi小助手帮我进行了懒人版的转换,是它的智能给予我了效率,让我能顺利发表这篇文章。

也感谢所有支持我的人,是你们的鼓励与支持推动我前进,让我有了更多的动力,谢谢!

(END……对了,话说一键三连不过分吧?👍🏼📂✅🙏🏼)

  • 9
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值