[刷题]蓝桥杯(z字矩阵,十字徽章)

蓝桥杯22年模拟赛的某题,按z字形输出矩阵

0123
1234
2345

输出顺序为(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;
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值