求解n阶螺旋矩阵问题(模拟与递归)

题目描述
创建n阶螺旋矩阵并输出。
输入
输入包含多个测试用例,每个测试用例为一行,包含一个正整数n(1<=n<=50),以输入0表示结束。
输出
每个测试用例输出n行,每行包括n个整数,整数之间用一个空格分割。
样例输入
4
0
样例输出
1 2 3 4
12 13 14 5
11 16 15 6
10 9 8 7


ps:对于这个题目本人很有感慨,之前已经遇到过两次了,但是因为自己觉得有点难,又觉得不重要,感觉有点偏僻,但是这次居然在自己的作业中遇到了这个题目,我觉得有必要写一篇题解来弥补我的过失~
先上一篇模拟题解,感觉模拟题解很容易理解,也容易编写,按照题目意思模拟一遍,在需要的地方变换方向,具体可以看代码理解,读者可以试图在纸上手动模拟一遍,我也是在纸上模拟一遍才理解的

#include 
using namespace std;
int a[100][100];
void func(int n)
{
    int x = 0, y = -1;        //x,y表示当前数组要赋值的位置
    int x_add = 0, y_add = 1; //每次赋值时,x和y的增量
    int num = n, num_add = n; //num:移动方向发生变化的转变点,num_add:每次转变时num的增量
    for (int i = 1; i <= n * n; ++i)
    {
        x += x_add;
        y += y_add;
        a[x][y] = i;
        if (i == num) //每次移动方向发生改变的判断条件
        {
            if (y_add == 1 || y_add == -1) //横向变纵向
            {
                x_add = y_add;
                y_add = 0;
                num_add--;      //为下一次变向做准备,因为这列的最后一个元素也是变换成行的第一个元素,为了不重复计算,所以减去一
                num += num_add; //下一次变向的终点
            }
            else //纵向变横向
            {
                y_add = -x_add;
                x_add = 0;
                num += num_add; //因为一定会先进行横向变纵向,所以此时的num_add早已不是初始化定义的num_add,显然就不用了减一操作了
            }
        }
    }
}
int main()
{
    int n;
    while (~scanf("%d", &n))
    {
        func(n);
        for (int i = 0; i < n; ++i)
        {
            for (int j = 0; j < n; ++j)
                printf("%d ", a[i][j]);
            printf("\n");
        }
    }
    return 0;
}

递归
ps:我们可以把这个这个看成先进行外层打印,再进行内层打印,因为他的规模大致一样,所以我们就可以用递归来编写代码,如果矩阵是一层或者两层那么要特别判断一下,因为这个是递归结束条件(奇数层偶数层),如果大于两层,那么我们先做外层,做完外层之后那么内层的长度就是外层长度减二,这个就相当于打正方形套着一个小正方形,这样递归的意思就很明显了,而且下一次递归的长度也就知道了。

#include 
using namespace std;
const int maxn = 60;
int n;
int a[maxn][maxn];
void f(int s, int e, int len, int k) //len表示矩阵的边长,也属于一个问题参量 , k表示当前是第几个矩阵
{
    if (len == 1) //递归边界(奇数层)
    {
        a[k][k] = s;
        return; //结束
    }
    else if (len == 2) //(偶数层)
    {
        a[k][k] = s++;
        a[k][k + 1] = s++;
        a[k + 1][k + 1] = s;
        a[k + 1][k] = e;
        return; //结束
    }
    int col = n + 1 - k; //表示右边框的列号和下边框的行号,也就是截止打印的最大值
    int x = s;
    //矩阵上边框
    for (int j = k; j <= col; j++)
        a[k][j] = x++;
    //矩阵右边框
    for (int i = k + 1; i <= col; i++)
        a[i][col] = x++;
    //矩阵下边框
    for (int j = col - 1; j >= k; j--)
        a[col][j] = x++;
    //矩阵左边框
    for (int i = col - 1; i >= k + 1; i--)
        a[i][k] = x++;
    f(x, n * n, len - 2, k + 1); //递归,填充小螺旋矩阵
    //内层递归长度比外层少2
}
int main()
{
    while (~scanf("%d", &n) && n)
    {
        f(1, n * n, n, 1); //从k = 1开始,第一个矩阵
        for (int i = 1; i <= n; i++)
        {
            for (int j = 1; j <= n; j++)
                printf("%d ", a[i][j]);
            printf("\n");
        }
    }
    return 0;
}

心简单,世界也就简单

你可能感兴趣的:(求解n阶螺旋矩阵问题(模拟与递归))