随手练——“打印”各种图形(宏观调度问题)
- 将矩阵(二维数组)旋转90°
如果只是要求旋转后输出,非常简单:
#include <iostream> using namespace std; int f[100][100]; int main() { int n, count = 1; cin >> n; printf("原矩阵:\n"); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { f[i][j] = count++; printf("%4d",f[i][j]); } printf("\n"); } printf("旋转之后:\n"); for (int j = 0; j < n; j++) { for (int i = n - 1; i >= 0; i--) { printf("%4d", f[i][j]); } printf("\n"); } return 0; }
如果要求存回去,再开个数组倒腾一下就好。
但如果要求空间复杂度O(1),就得这样做了:
#include <iostream> using namespace std; int f[100][100]; void print(int p0,int p1) { if (p0 >= p1) { return; } for (int i = p0; i < p1; i++) { int t = f[p0][i]; f[p0][i] = f[p1 - i][p0]; f[p1 - i][p0] = f[p1][p1 - i]; f[p1][p1 - i] = f[p0 + i][p1]; f[p0 + i][p1] = t; } print(p0 + 1, p1 - 1); } int main() { int n, count = 1; cin >> n; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { f[i][j] = count++; } } print(0,n-1); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { printf("%4d", f[i][j]); } printf("\n"); } return 0; }
- 正方形、长方形矩阵
给定左上角、右下角坐标,作为基准,给全局数组赋值。
因为是正方形矩阵,对角线上,横纵坐标是一样的,给两个数就够了。
#include <stdio.h> int f[10][10]; void print(int p0,int p1) { static int count = 1; if (p0 >= p1) { if (p0 == p1) f[p0][p1] = count; return; } for (int i = p0; i <= p1; i++)f[p0][i] = count++; for (int i = p0 + 1; i <= p1; i++)f[i][p1] = count++; for (int i = p1 - 1; i >= p0; i--)f[p1][i] = count++; for (int i = p1 - 1; i > p0; i--)f[i][p0] = count++; print(p0 + 1, p1 - 1); } int main() { int n; scanf("%d",&n); print(0, n - 1); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { printf("%4d",f[i][j]); } printf("\n"); } return 0; }
方法和正方形几乎一致:
#include <stdio.h> int f[100][100]; void print(int x0,int y0,int x1,int y1) { static int count = 1; if (x0 >= x1 || y0 >= y1) { if (x0 == x1) { for (int i = y0; i <= y1; i++)f[x0][i] = count++; } else { for (int i = x0; i <= x1; i++)f[i][y0] = count++; } return; } for (int i = y0; i <= y1; i++)f[x0][i] = count++; for (int i = x0 + 1; i <= x1; i++)f[i][y1] = count++; for (int i = y1 - 1; i >= y0; i--)f[x1][i] = count++; for (int i = x1 - 1; i > x0; i--)f[i][y0] = count++; print(x0 + 1, y0 + 1, x1 - 1, y1 - 1); } int main() { //m行,n列 int m,n; scanf("%d%d",&m,&n); print(0, 0, m - 1, n - 1); for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { printf("%4d",f[i][j]); } printf("\n"); } return 0; }
从左上角开始,打印到右下角(按数据在线中的位置从左往右输出,每条对角线占一行)。
主要是一种思想,这个题如果想着,怎么转换输出形式能够输出成这样,就太难了。
我们就解决 给定左下,右上两个点 输出 一条线 ,后面就好做了。
#include <iostream> using namespace std; int f[100][100]; void print(int lx,int ly,int rx,int ry) { while (lx >= rx) { printf("%4d", f[lx--][ly++]); } printf("\n"); } int main() { int m, n, count = 1; //m行n列 cin >> m >> n; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { f[i][j] = count++; } } int ax = 0, ay = 0, bx = 0, by = 0; //以ax,ay为例,起初ax每次+1,ay不变,当ax到最后一行,ax就不变了,ay开始+1 while (ay != n) { print(ax,ay,bx,by); //要先给ay赋值,先写ax拐角处就不做了 ay = ax == m - 1 ? ay + 1 : ay; ax = ax == m - 1 ? ax : ax + 1; bx = by == n - 1 ? bx + 1 : bx; by = by == n - 1 ? by : by + 1; } return 0; }