蓝桥杯22年模拟赛的某题,按z字形输出矩阵
0 | 1 | 2 | 3 |
1 | 2 | 3 | 4 |
2 | 3 | 4 | 5 |
输出顺序为(0,0)-> (0,1)->(1,0)->(2,0)->(1,1)->(0,2)......(1,3)->(2,3)
样例的输出结果应为011222333445
处理方法1:
利用矩阵自身的性质,同一条斜线上的元素,他的行和列序号和是不变的,且最后一个元素正好是列数和行数之和,也就是最大的.按照行列序号之和和遍历顺序可以分为
(0,0)[0] (0,1) (1.0)[1] (2,0) (1,1) (0,2)[2] (0,3) (1,2) (2,1)[3] (1,3) (2,2) (2,3)[4]
遍历的时候按照行列数之和进行遍历,按照题目要求,
如果和是奇数,就从(x,0)--->(0,x)变化
如果和是偶数,就从(0,x)--->(x.0)变化,这个具体按照题目的要求进行修改,反正连续的z字输出就是这个思路
以及,要判断一下当前的行列序号属于矩阵的范畴之内,代码示例如下
void lkp(int row, int col) {//假设输入的数字为 ( 2,3 )同样也是矩阵的限制
//这里再进行手动输入矩阵,为了运行方便这里数组已经录入
int arr[3][4] = { {0,1,2,3},{1,2,3,4},{2,3,4,5} };
for (int i = 0; i <= row + col; i++) {
if (i % 2 == 0) {
for (int x = i; x >= 0; x--) {
if ((0 <= x && x <= row) && (0 <= (i - x) && (i - x) <= col)) {
cout << arr[x][i - x] << " ";
}
}
}
else {
for (int x = 0; x <= i; x++) {
if ((0 <= x && x <= row) && (0 <= (i - x) && (i - x) <= col)) {
cout << arr[x][i - x] << " ";
}
}
}
}
}
进行优化:
上面的处理中仍然是过于暴力比如说过多的比较和判断,判断这个元素是否属于矩阵内部
(再说吧)
18年真题(十字徽章)
原题的描述如下:
问题描述
小明为某机构设计了一个十字型的徽标(并非红十字会啊),如下所示:
..$$$$$$$$$$$$$..
..$...........$..
$$$.$$$$$$$$$.$$$
$...$.......$...$
$.$$$.$$$$$.$$$.$
$.$...$...$...$.$
$.$.$$$.$.$$$.$.$
$.$.$...$...$.$.$
$.$.$.$$$$$.$.$.$
$.$.$...$...$.$.$
$.$.$$$.$.$$$.$.$
$.$...$...$...$.$
$.$$$.$$$$$.$$$.$
$...$.......$...$
$$$.$$$$$$$$$.$$$
..$...........$..
..$$$$$$$$$$$$$..
对方同时也需要在电脑dos窗口中以字符的形式输出该标志,并能任意控制层数。
输入格式
一个正整数 n (n<30) 表示要求打印图形的层数。
输出格式
对应包围层数的该标志。
样例输入1
1
样例输出1
..$$$$$..
..$...$..
$$$.$.$$$
$...$...$
$.$$$$$.$
$...$...$
$$$.$.$$$
..$...$..
..$$$$$..
样例输入2
3
样例输出2
..$$$$$$$$$$$$$..
..$...........$..
$$$.$$$$$$$$$.$$$
$...$.......$...$
$.$$$.$$$$$.$$$.$
$.$...$...$...$.$
$.$.$$$.$.$$$.$.$
$.$.$...$...$.$.$
$.$.$.$$$$$.$.$.$
$.$.$...$...$.$.$
$.$.$$$.$.$$$.$.$
$.$...$...$...$.$
$.$$$.$$$$$.$$$.$
$...$.......$...$
$$$.$$$$$$$$$.$$$
..$...........$..
..$$$$$$$$$$$$$..
提示
请仔细观察样例,尤其要注意句点的数量和输出位置。
这题的第一个难点在于看出来这个图有什么规律。。。碰上这种题目建议画个矩阵,题目的描述真的是模棱两可而且一般不是解题思路;
这题的解题思路:(1)把左上角矩阵画出来(2)其他三个区域用对称画出来
不用管是嵌套层数了,矩阵的长度为4×嵌套层数+5,(注意末尾坐标为4*n+5-1)
化成矩阵的话是这个样子(这是其中一个左上角的情况)
@ | @ | @ | @ | @ | ||
@ | ||||||
@ | @ | @ | @ | @ | @ | |
@ | @ | |||||
@ | @ | @ | @ | @ | ||
@ | @ | @ | ||||
@ | @ | @ | @ | @ |
这样的话能找到的规律其实有很多,这里我们选择其中一种:以左下方向的对角线为基准,左上角起始顶点为(0.0),遍历得到(2,2),(4,4),(6,6)这些点
然后以这些点为起始点,往上和往左侧的三个点都要进行标记
最后,从标记的尽头开始,向右或者向下开始无限延伸,直到边界位置
左上角的图形就能够构建出来(注意这里中心的十字线也算上了)
代码实现如下
//下面这个是附上初始数值
for(int i=0;i<=length/2;i++){
for(int j=0;j<=length/2;j++){
arr[i][j]='.';
}
}
for(int x=2,y=2;x<=length/2;x+=2,y+=2){//左上角区域的
arr[x][y]=arr[x-1][y]=arr[x-2][y]=arr[x][y-1]=arr[x][y-2]='$';
for(int m1=x;m1<=length/2;m1++)
arr[m1][y-2]='$';
for(int m2=y;m2<=length/2;m2++)
arr[x-2][m2]='$';
}
至于其他的三个区域,使用抽对称复制就行了
最后完整的代码实现如下
void cross(int n){
//一开始的长度计算错了,长度确实是4*n+5,但是最后一位的坐标应该是4*n+5-1才对
int length=4*n+5-1;
//下面这个是附上初始数值
for(int i=0;i<=length/2;i++){
for(int j=0;j<=length/2;j++){
arr[i][j]='.';
}
}
for(int x=2,y=2;x<=length/2;x+=2,y+=2){//左上角区域的
arr[x][y]=arr[x-1][y]=arr[x-2][y]=arr[x][y-1]=arr[x][y-2]='$';
for(int m1=x;m1<=length/2;m1++)
arr[m1][y-2]='$';
for(int m2=y;m2<=length/2;m2++)
arr[x-2][m2]='$';
}
//其他三个区域直接用对称就能处理了
for(int x=0;x<=length/2;x++){//右上角
for(int y=length/2;y<=length;y++){
arr[x][y]=arr[x][length-y];
}
}
for(int x=length/2;x<=length;x++){//左下角
for(int y=0;y<=length/2;y++){
arr[x][y]=arr[length-x][y];
}
}
for(int x=length/2;x<=length;x++){//左下角
for(int y=length/2;y<=length;y++){
arr[x][y]=arr[length-x][length-y];
}
}
//输出所有的字符
for(int i=0;i<=length;i++){
for(int j=0;j<=length;j++){
cout<<arr[i][j];
}
cout<<endl;
}
}