【题目链接】
【题目考点】
1. 递归/递推:分形图
2. 分治
【解题思路】
考察输出样例,可以发现规律,当矩阵边长为1,2,4,8的时候,如果将矩阵分为四个区域,那么左上方与右下方相同,右上方与左下方相同。
根据这一规律,该题有递推与递归两种解法。
解法1:递推
一个边长为n的矩阵,边长的一半记为half, h a l f = n 2 half = \frac{n}{2} half=2n。将该矩阵等分为四部分:
- 左上部:行坐标:1~half,列坐标:1~half
- 右上部:行坐标:1~half,列坐标:half+1~n
- 左下部:行坐标:half+1~n,列坐标:1~half
- 右下部:行坐标:half+1~n,列坐标:half+1~n
左上部的数据是已知的,当前需要做的是根据左上部的数据推导出其他三个部分的数据。
记左上部第i行第j列的位置为(i,j),值记为a[i][j]
,其对应的其他三部分的位置及值的情况如下
- 左上部(i, j)对应右上部(i,j+half),数值应该为在
a[i][j]
基础上增加half,即a[i][j+half] = a[i][j] + half
- 左上部(i, j)对应左下部(i+half,j),数值应该为在
a[i][j]
基础上增加half,即a[i+half][j] = a[i][j] + half
- 左上部(i, j)对应右下部(i+half,j+half),数值与
a[i][j]
相同,即a[i+half][j+half] = a[i][j]
。
先将a[1][1]
设为1,然后考虑边长为2的矩阵,此时左上部为a[1][1]
是已知的。填充好边长为2的矩阵后,考虑边长为4的矩阵,此时左上部为已知的。而后再考虑边长为8的矩阵。每次考虑的矩阵边长乘以2,最后考虑边长为
2
m
2^m
2m的矩阵。
解法2:递归
- 递归问题:用从s开始的数字填充左上角为(x,y),边长为k的矩阵。
- 递归关系:
记half = k/2
,表示矩阵边长的一半。将以(x,y)为左上角,边长为k的矩阵分为四个部分: - 左上部:以(x,y)为左上角,边长为half,数字从s开始
- 右上部:以(x,y+half)为左上角,边长为half,数字从s+half开始
- 左下部:以(x+half,y)为左上角,边长为half,数字从s+half开始
- 右下部:以(x+half,y+half)为左上角,边长为half,数字从s开始
填充这四个部分的矩阵是子问题,可以递归求解。四个子矩阵填充后,本矩阵即填充完毕。 - 递归出口:如果该矩阵边长为1,左上角为(x,y),数字从s开始。那么就直接赋值
a[x][y]=s
【题解代码】
解法1:递推
#include<bits/stdc++.h>
using namespace std;
#define N 1025
int a[N][N];
int main()
{
int n, m, half;
cin >> m;
n = pow(2, m);//矩阵最大边长
a[1][1] = 1;
for(int k = 2; k <= n; k *= 2)//填充边长为k的矩阵
{
half = k/2;//矩阵边长的一半
for(int i = 1; i <= half; ++i)
for(int j = 1; j <= half; ++j)
{
a[i+half][j+half] = a[i][j];//填充右下部
a[i][j+half] = a[i+half][j] = a[i][j] + half;//填充右上部与左下部
}
}
for(int i = 1; i <= n; ++i)//输出矩阵
{
for(int j = 1; j <= n; ++j)
cout << a[i][j] << ' ';
cout << endl;
}
return 0;
}
解法2:递归
#include<bits/stdc++.h>
using namespace std;
#define N 1025
int a[N][N];
//要填的数字为s~s+k-1, 矩阵边长:k, 矩阵左上角为(x, y)
void setMatrix(int s, int k, int x, int y)
{
if(k == 1)
{
a[x][y] = s;
return;
}
int half = k/2;
setMatrix(s, half, x, y);//左上部
setMatrix(s+half, half, x, y+half);//右上部
setMatrix(s+half, half, x+half, y);//左下部
setMatrix(s, half, x+half, y+half);//右下部
}
int main()
{
int n, m;
cin >> m;
n = pow(2, m);//矩阵边长
setMatrix(1, n, 1, 1);//左上角为(1,1),填充数值为1~n
for(int i = 1; i <= n; ++i)//输出矩阵
{
for(int j = 1; j <= n; ++j)
cout << a[i][j] << ' ';
cout << endl;
}
return 0;
}