7-269 旋转方阵

对于一个奇数n阶方阵,请给出经过顺时针方向m次旋转后的结果。

输入格式:

测试数据有多组,处理到文件尾。每组测试的第一行输入2个整数n,m(1<n<20,1≤m≤100),接下来输入n行数据,每行n个整数。

输出格式:

对于每组测试,输出奇数阶方阵经过m次顺时针方向旋转后的结果。每行中各数据之间留一个空格。

输入样例:

3 2
4 9 2
3 5 7
8 1 6
3 1
4 9 2
3 5 7
8 1 6
3 7
4 9 2
3 5 7
8 1 6
3 8
4 9 2
3 5 7
8 1 6

输出样例:

6 1 8
7 5 3
2 9 4
8 3 4
1 5 9
6 7 2
2 7 6
9 5 1
4 3 8
4 9 2
3 5 7
8 1 6

来源:

[1] 黄龙军, 等. 大学生程序设计竞赛入门—C/C++程序设计(微课视频版), 北京:清华大学出版社, 2020.11. ISBN:9787302564744
[2] 黄龙军.程序设计竞赛入门(Python版),北京:清华大学出版社,2021.4. ISBN:9787302571230

代码长度限制

16 KB

时间限制

400 ms

内存限制

64 MB

思路

主函数

  1. 使用 while 循环处理多组测试数据,直到输入结束为止。
  2. 每次读入两个整数 n 和 m,分别表示方阵的行列数和要旋转的次数。
  3. 声明二维数组 a 存储方阵中的元素。使用双重循环依次读入每个元素,存储到数组 a 中。
  4. 调用函数 rotate() 执行顺时针旋转操作。函数接受三个参数:数组 a、方阵的行列数 n 和要旋转的次数 m
  5. 遍历数组 a,输出旋转后的结果。

rotate()函数

  1. 首先,外层循环 for (k = 0; k < m; k++) 表示需要旋转的次数。每一次旋转操作都会将二维数组顺时针方向旋转 90 度。
  2. 然后,我们遍历二维数组中的每个子区间。对于一个 n × n 的方阵,我们可以分为 n/2 个子区间,每个子区间由四个位置组成,即左上角、右上角、右下角和左下角。
  3. 对于每个子区间,我们使用三重循环依次交换四个位置的值。具体地,内部的两重循环用于遍历子区间中的元素,第三重循环是为了执行交换操作。其中,变量 i 和 j 分别表示二维数组中的行和列,变量 t 是一个临时变量,用于存储要交换的两个元素的值。
  4. 交换操作如下:
    • 首先,将左上角的元素 a[i][j] 存储到变量 t 中。
    • 然后,将右上角的元素 a[n-j-1][i] 移动到左上角的位置 a[i][j] 上。注意,这里的 n-j-1 表示列数为 j 的元素在旋转后的位置,即原来的倒数第 j 行。
    • 接着,将右下角的元素 a[n-i-1][n-j-1] 移动到右上角的位置 a[n-j-1][i] 上。注意,这里的 n-i-1 表示行数为 i 的元素在旋转后的位置,即原来的倒数第 i 列;n-j-1 表示列数为 j 的元素在旋转后的位置,即原来的倒数第 j 行。
    • 然后,将左下角的元素 a[j][n-i-1] 移动到右下角的位置 a[n-i-1][n-j-1] 上。注意,这里的 j 表示列数为 j 的元素在旋转后的位置,即原来的第 j 行;n-i-1 表示行数为 i 的元素在旋转后的位置,即原来的倒数第 i 列。
    • 最后,将变量 t 中存储的左上角元素的值赋给左下角的位置 a[j][n-i-1] 上。

经过 m 次循环后,方阵中的元素就完成了顺时针旋转操作。

代码

#include <stdio.h>

void rotate(int a[][20], int n, int m)
{
    int i, j, k, t;
    for (k = 0; k < m; k++) { // 循环执行 m 次旋转操作
        for (i = 0; i < n / 2; i++) { // 遍历每个子区间
            for (j = i; j < n - i - 1; j++) { // 交换子区间中的四个元素
                t = a[i][j]; // 存储左上角的元素
                a[i][j] = a[n - j - 1][i]; // 将右上角的元素移到左上角
                a[n - j - 1][i] = a[n - i - 1][n - j - 1]; // 将右下角的元素移到右上角
                a[n - i - 1][n - j - 1] = a[j][n - i - 1]; // 将左下角的元素移到右下角
                a[j][n - i - 1] = t; // 将存储在变量 t 中的左上角元素赋值到左下角
            }
        }
    }
}

int main()
{
    int n, m, a[20][20];
    while (scanf("%d%d", &n, &m) != EOF) { // 处理多组测试数据
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                scanf("%d", &a[i][j]); // 读入每个元素
            }
        }
        rotate(a, n, m); // 执行旋转操作
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                printf("%d", a[i][j]); // 输出二维数组中的每个元素
                if (j == n - 1) { // 如果是该行的最后一个元素,输出换行符
                    printf("\n");
                } else { // 否则,输出空格
                    printf(" ");
                }
            }
        }
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吾乃宇宙欠债王

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值