P5461 赦免战俘
复制 Markdown
退出 IDE 模式
题目背景
借助反作弊系统,一些在月赛有抄袭作弊行为的选手被抓出来了!
题目描述
现有 2
n
×2
n
(n≤10) 名作弊者站成一个正方形方阵等候 kkksc03 的发落。kkksc03 决定赦免一些作弊者。他将正方形矩阵均分为 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
呜呜呜呜呜呜呜呜呜呜呜呜呜呜呜呜呜呜呜呜呜呜呜呜我就知道,一有一点点算法相关强度就上来了我就彻底GG呜呜呜呜呜呜呜呜呜呜呜呜呜呜呜呜呜呜呜呜呜呜呜呜我不要敲代码我真的写不出来,递归从大二就不太会,当时那个汉诺塔也是狠狠折磨我,一直到现在,分治问题又要递归呜呜呜呜呜呜呜呜呜呜呜呜呜呜呜呜呜呜呜呜呜呜呜呜窝补药参加蓝桥杯了,真的太痛苦了😭😭😭
def free(n,x,y):
if(n==1):
return
for i in range(x,x+n//2):
for j in range(y,y+n//2):
s[i][j] = 0
free(n//2,x,y+n//2)
free(n//2,x+n//2,y)
free(n//2,x+n//2,y+n//2)
n = 2**int(input())
s = [[1]*n for _ in range(n)]
free(n,0,0)
for i in range(n):
for j in range(n):
print(s[i][j],end=" ")
print("")
核心在于free函数,递归最重要的是递归体和递归出口(不记得了,当时课本上应该是这样说的,不管了,我说是这两个就是这两个)。
这里的递归出口就是n,观察(也可能是由数学知识)可以发现分治input()次后结束,也就是n不断/2直到变成1,所以最开始要先设置出口。
接下来是free战俘,也就是数组某一位置变0,这里注意范围,x是(x,x+n//2),y是(y,y+n//2),也就是左上角的位置。
最后是递归体,一开始已经处理了左上角全部需要等于0,接着先递归右上角,即:free(n//2,x,y+n//2)。然后是左下角,即:free(n//2,x+n//2,y)。最后是右下角,即:free(n//2,x+n//2,y+n//2)。
迷迷糊糊SOS,还是觉得好神奇,世界上怎么会有发明出递归这个东西这么聪明的人…