回形取数
问题描述
回形取数就是沿矩阵的边取数,若当前方向上无数可取或已经取过,则左转90度。一开始位于矩阵左上角,方向向下。
输入格式
输入第一行是两个不超过200的正整数m, n,表示矩阵的行和列。接下来m行每行n个整数,表示这个矩阵。
输出格式
输出只有一行,共mn个数,为输入矩阵回形取数得到的结果。数之间用一个空格分隔,行末不要有多余的空格。
样例输入
3 3
1 2 3
4 5 6
7 8 9
样例输出
1 4 7 8 9 6 3 2 5
样例输入
3 2
1 2
3 4
5 6
样例输出
1 3 5 6 4 2
问题分析:
关于回形问题,或者是数组中顺时针或者逆时针走法输出的问题,递归方法是一个不错的解决问题的方法,只要理解如何调转方向,就没问题
就本题而言,步骤如下:
1,设置一个标志数组,用来判定是否已经打印过该位置上的数据
2,写出打印输出的判断条件,除了要满足在数组内(也就是不超过 m行 n列),还要判断是否打印过,也就是标志位数组的值是否为0
3,设置一个常数变量 cn++, 根据 cn%4 的值来调转方向(数组就四条边)
4,递归的使用,以及递归函数中 参数的变化(调转方向)
代码展示(已验证):
#include <stdio.h>
#include <stdlib.h>
#include "string.h"
#define MAX 200
int a[MAX][MAX]; //存储输入的数据
int b[MAX][MAX]; //是否取过的标志位 数组
int m, n;
int cn = 0;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
void print(int i,int j) //从a[0][0]位置 开始打印
{
//int b[MAX][MAX];
//memset(b, 0, sizeof(b)); //初始化 标志数组b[][]=0
//int cn = 0; //cycle number cn 圈数 一个矩阵 四条边 每次输出一条边的数据 可用递归算法
// 每次输出一行或者一列 cn++
//int i = 0, j = 0; 不能在递归中这样给数据赋值 需要提前赋值结束 可以定义全局变量
if (i<m && i>=0 && j<n && j>=0 && b[i][j]==0) //判定输出条件
{
printf("%d ", a[i][j]);
b[i][j] = 1;
}
else // 当不满足条件时 说明输出位置已经到了边缘 进行cn++
{
cn++;
return; //跳出判定条件
}
// 递归开始 从第一列开始 两圈递归输出所有数据
if (cn % 4 == 0)
print(i + 1, j);
if (cn % 4 == 1)
print(i, j + 1);
if (cn % 4 == 2)
print(i - 1, j);
if (cn % 4 == 3)
print(i, j - 1);
// 一圈 递归输出的数据会有丢失 所以要再加一圈递归
if (cn % 4 == 0)
print(i + 1, j);
if (cn % 4 == 1)
print(i, j + 1);
if (cn % 4 == 2)
print(i - 1, j);
if (cn % 4 == 3)
print(i, j-1);
return; //void
}
int main(int argc, char *argv[])
{
// int a[MAX][MAX];
int i, j;
scanf("%d%d", &m, &n);
for (i = 0; i < m;i++)
for (j = 0; j < n; j++)
{
scanf("%d", &a[i][j]);
}
memset(b, 0, sizeof(b));//初始化 标志数组b[][]=0 string.h
print(0,0); //调用函数打印输出
return 0;
}
泡泡:
其实这一类型的题目终点就在于 递归的使用 以及 遍历输出打印数组,牵扯到 :
参数变化-->改变方向,
cn 变量 --> 改变方向,
递归调用-->遍历打印,
标志位数组-->是否打印过
判断条件-->打印输出
ok,收工。