首页 > 试题广场 >

蛇形矩阵

[编程题]蛇形矩阵
  • 热度指数:6106 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解
给你一个整数n,输出n∗n的蛇形矩阵。

输入描述:
输入一行,包含一个整数n


输出描述:
输出n行,每行包含n个正整数,通过空格分隔。

1<=n<=1000
示例1

输入

4

输出

1 2 6 7
3 5 8 13
4 9 12 14
10 11 15 16

每个颜色的折线表示一次大循环。
看图可知,这样难免会发生越界的情况,
所以给数组元素赋值时加个判断条件,
当行号和列号都不超过n时赋值,超过n时则不赋。
row为行号,
col为列号,
count为计数器,是每次给元素赋的值。
#include <stdio.h>
int main()
{
    int n;
    scanf("%d", &n);
    int count = 1;
    int row = 0;
    int col = 0;
    int arr[1000][1000] = {0};
    while(count <= n*n)
    {
        for(int i=0; i<2; i++)
        {
            if(row<n && col<n)
                arr[row][col] = count++;
            col++;
        }
        col--;
        while(col)
        {
            row++;
            col--;
            if(row<n && col<n)
                arr[row][col] = count++;
        }
        row++;
        while(row)
        {
            if(row<n && col<n)
                arr[row][col] = count++;
            row--;
            col++;
        }  
    }
    for(int i=0; i<n; i++)
    {
        for(int j=0; j<n; j++)
            printf("%d ", arr[i][j]);
        printf("\n");
    }
    return 0;
}


发表于 2022-04-02 00:04:48 回复(1)
import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner in=new Scanner(System.in);
        int n=in.nextInt();
        int[][] a=new int[n][n];
        int z=0,i=0,j=0;
        while(z<n*n){
            for(j=0;i>=0;i--,j++)
                if(i<n && j<n)
                    a[i][j]=++z;
            for(i=0;j>=0;i++,j--)
                if(i<n && j<n)
                    a[i][j]=++z;
        }
        for(int[] k:a) {
            for (int p : k)
                System.out.print(p + " ");
            System.out.println();
        }
   比较简单
发表于 2022-07-27 17:27:56 回复(2)
#include<stdio.h>
int main()
{
    int n;
    scanf("%d",&n);
    int arr[1001][1001]={0};
    arr[0][0]=1;
    int count=2;
    int pos=1;//1表示右上,-1表示左下
    int i=0,j=0;//i表示行,j表示列
    while(count<=n*n)
    {
        //先判定四种情况
        if(i==0&&j<n-1&&pos==1)//上边界,行不变,列增加
        {
            arr[i][++j]=count++;
            pos=-1;//改变方向
        }
        else if(i<n-1&&j==0&&pos==-1)//左边界,行增加,列不变
        {
            arr[++i][j]=count++;
            pos=1;
        }
        else if(i<n-1&&j==n-1&&pos==1)//右边界,行增加,列不变
        {
            arr[++i][j]=count++;
            pos=-1;
        }
        else if(i==n-1&&j<n-1&&pos==-1)//下边界,行不变,列增加
        {
            arr[i][++j]=count++;
            pos=1;
        }
        else if(pos==1)//右上
        {
            arr[--i][++j]=count++;
        }
        else if(pos==-1)//左下
        {
            arr[++i][--j]=count++;
        }
    }
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
        {
            printf("%d ",arr[i][j]);
        }
        printf("\n");
    }
    return 0;
}

发表于 2022-03-26 15:14:46 回复(1)
#include<stdio.h>
int main() {
    int n, arr[1000][1000], cur = 0;
    scanf("%d", &n);
    int i = 0, j = 0;//i代表行,j代表列
    for (int k = 0; k < n - 1; k++) {   //循环次数n-1次
        int b = j;
        for (i = 0; j < b + 2; j++) {   //一次循环内的横向走向
            if (j < n)
                arr[i][j] = ++cur;
        }
        for (i = 1, j = j - 2; j >= 0; i++, j--) {   //右上到左下走向
            if (i >= 0 && j >= 0 && j < n && i < n)
                arr[i][j] = ++cur;
        }
        for (j = 0; i > 0; i--, j++) {     //左下到右上走向
            if (i >= 0 && j >= 0 && j < n && i < n)
                arr[i][j] = ++cur;
        }
    }
    for (i = 0; i < n; i++) {
        for (j = 0; j < n; j++)
            printf("%d ", arr[i][j]);
        printf("\n");
    }
    return 0;
}

发表于 2022-08-04 18:20:33 回复(1)
#include <stdio.h>
//拐弯分为u1横拐和u2竖拐,横拐行不变 列加一;竖拐列不变 行加一
//其他运动方式k分为k1斜上和k2斜下。 斜上:行递减,列递加;斜下:行递加,列递减
//k1,k2,u1,u2与n的关系:
int main() {
    int n = 0;
    int i = 0, j = 0;
    int nj = 0;
    int ni = 0;
    scanf("%d", &n);
    if (n == 1) {
        printf("1 ");
        return 0;
    }
    int arr[20][20] = { 0 };
    int a = 1;
    arr[0][0] = a;
    a++;
    while (a < n * n - 2) {
        if (j < n - 1) {
            j++;
        } else {
            nj++;
            j++;
            while (j > (1 + ni)) {
                j--;
                i++;
                arr[i][j] = a;
                a++;
            }

            ni++;

            goto star1;
        }
        arr[i][j] = a;
        a++;
        while (j > 0) {
            j--;
            i++;
            arr[i][j] = a;
            a++;
        }
star1:
        if (i < n - 1) {
            i++;
        } else {
            ni++;
            i++;
            while (i > (1 + nj)) {
                i--;
                j++;
                arr[i][j] = a;
                a++;
            }

            nj++;

            goto star2;
        }
        arr[i][j] = a;
        a++;
        while (i > 0) {
            i--;
            j++;
            arr[i][j] = a;
            a++;
        }
star2:
        ;
    }
    arr[n - 2][n - 1] = a;
    a++;
    arr[n - 1][n - 2] = a;
    a++;
    arr[n - 1][n - 1] = a;
    for (int u = 0; u < n; u++) {
        for (int v = 0; v < n; v++) {
            printf("%d ", arr[u][v]);
        }
        printf("\n");
    }

    return 0;
}

发表于 2024-08-14 12:41:09 回复(0)
#include <stdio.h>

int main() {
	int n;
	scanf("%d", &n);
	int s[n][n];                                
	int i;
	int x = 0, y = 0;									//数组元素的坐标 
	int flag;											//斜走方式:1为向右上,0为向左下 
	int min = 0, max = n-1;								//边缘位置 
	i = 1;
	s[x][y] = i++;
	while ( i <= n*n ) {								
		if ( x == min && y < max ) {					//斜走完成后在上边缘,向右走 
			y++;										//右上角除外,且修改斜走方式为向左下 
			flag = 0;
		} else if ( y == max && x < max ) {				//斜走完成后在右边缘,向右走 
			x++;										//右下角除外,且修改斜走方式为向左下
			flag = 0; 
		} else if ( y == min && x < max && x > 0 ) {	//斜走完成后在左边缘,向右走 
			x++;										//左上,左下角除外,且修改斜走方式为向右上
			flag = 1;
		} else if ( x == max && y < max ) {				//斜走完成后在右方,向右走 
			y++;										//右下角除外,且修改斜走方式为向右上
			flag = 1;
		}
		s[x][y] = i++;									
		if ( flag == 0 ) {								
			while ( y > min && x < max ) {				//左下走,直到碰到边缘 
				x++;
				y--;
				s[x][y] = i++;
			}
		} else {										//右上走,直到碰到边缘 
			while ( x > min && y < max ) {
				x--;
				y++;
				s[x][y] = i++;
			}
		}
	}
	for ( i = 0; i < n; i++ ) {							//打印数组 
		for ( int j = 0; j < n; j++ ) {
			printf("%d ", s[i][j]);
		}
		printf("\n");
	}
}

发表于 2024-03-17 12:46:00 回复(0)
#include <stdio.h>

int main() {
    int n,a[1005][1005],count=2;
    scanf("%d",&n);
    int row=1,col=1,ci=1;//ci指一次左斜下+一次右斜上
    a[1][1]=1;
    while(count<=n*n){
        for(int i=row,j=col+1;j>=1;i++,j--){
            if(i<=n&&j<=n)a[i][j]=count++;
        }
        for(int i=row+2*ci,j=col-2*(ci-1);i>=1;i--,j++){
            if(i<=n&&j<=n)a[i][j]=count++;
        }
        ci++;
        col+=2;//第一次循环原点(1,1),第二次循环原点(3,1),以此类推
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++)printf("%d ",a[i][j]);
        printf("\n");
    }
    return 0;
}

发表于 2024-01-14 22:32:21 回复(0)
int main() {
    int arr[100][100];
    int n = 0, i = 0, j = 0, m = 1;
    scanf("%d", &n);
    int sum = n * n;
    while (m <= sum) {
        for (; (i >= 0) || (j >= n); ++j, --i) {
            if (j >= n) {
                j = n - 1;
                ++i;
                break;
            } else {
                arr[i][j] = m++;
            }
        }
        for (++i; (j >= 0)||(i >= n); ++i, --j) {
            if (i >= n) {
                i = n - 1;
                ++j;
                break;
            } else {
                arr[i][j] = m++;
            }
        }
        ++j;
    }
    for (i = 0; i < n; ++i) {
        for (j = 0; j < n; ++j) {
            printf("%d ", arr[i][j]);
        }
        printf("\n");
    }
    return 0;
}
发表于 2023-10-10 17:23:49 回复(0)
#include<iostream>
using namespace std;
int main()
{
    int n;
    cin>>n;
    int a[n][n];
    int m=0,num=1;
    while(m<=(2*n-2))
    {
        int z=m>n-1?m-(n-1):0;
        for(int i=z;i<=m-z;i++)
        {
            if(m%2==0)
                a[m-i][i]=num++;
            else
                a[i][m-i]=num++;
        }
        m++;
    }
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
            cout<<a[i][j]<<' ';
        cout<<endl;
    }
}
发表于 2022-07-27 23:12:27 回复(0)
#include <iostream>
#include <vector>
using namespace std;

int main(){
    int n;
    
    cin>>n;
    vector<vector<int>> arr(n,vector<int>(n));
    int row,start,flag=-1,num=1;
    for(int i=0;i<2*n-1;i++){
        row=min(i,n-1);//row表示行能到达的最大,i-row就表示列能到达的最大
        start=(flag==-1?row:(i-row));//统一,但是不能用row表示,因为下面for判断还是用row,就搞混了
        for(int j=start;(i-j)<=row&&j<=row;j+=flag){
            arr[j][i-j]=num++;
        }
//         if(flag==1){//不统一
//             for(int j=row;i-j<=row;j--){//表示从左下到右上的过程
//                 arr[j][i-j]=num++;
//             }
//         }else{
//             for(int j=i-row;j<=row;j++){//表示从右上到左下的过程
//                 arr[j][i-j]=num++;
//             }
//         }
        flag=-flag;
    }
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++)
            cout<<arr[i][j]<<' ';
        cout<<endl;
    }
    return 0;
}

发表于 2022-06-14 11:31:54 回复(0)
#include <stdio.h>
int main() {
    int a, k = 2, i = 0, j = 1;
    scanf("%d", &a);
    int arr[a][a];
    arr[0][0] = 1;
    while (1)
    {
        arr[i][j] = k++;
        while (j > 0)
        {
            i++, j--;
            arr[i][j] = k++;
        }
        if (i + j >= a - 1)
            break;
        i++;
        arr[i][j] = k++;
        while (i > 0)
        {
            i--, j++;
            arr[i][j] = k++;
        }
        if (i + j >= a - 1)
            break;
        j++;
    }
    for (i = 1; i < a; i++)
    {
        for (j = a - i; j < a; j++)
        {
            arr[i][j] = a * a + 1 - arr[a - 1 - i][a - 1 - j];
        }
    }
    for (i = 0; i < a; i++)
    {
        for (j = 0; j < a; j++)
        {
            printf("%d ", arr[i][j]);
        }
        printf("\n");
    }
    return 0;
}
发表于 2025-04-29 02:40:55 回复(0)
什么蛇皮呦 
发表于 2025-01-25 21:40:15 回复(1)
#include<stdio.h>
void snake_matrix(int arr[1000][1000],int n)
{
   int i = 0;
   int j = 0;
   int sum = 1;
   int k = 0;
    while(sum <= n*n)
    {
        while(k < n-1)   //上三角 
        {
            if(k % 2==0)
            {
               while(i>=0)  //斜向上
               {
                 arr[i][j]=sum;
                 sum++;
                 i--;
                 j++;
               }
               i++;       //校正起点
               k++;
            }
            if(k==n-1)
            break;
            if(k % 2 != 0)
            {
               while(j>=0)  //斜向下
               {
                  arr[i][j]=sum;
                  sum++;
                  j--;
                  i++; 
               }
               j++;   //校正起点
               k++;
            }
            if(k==n-1)
            break;
        }
        while(k >= n-1) // 下三角
        {
            if(k % 2 != 0)  //斜向下
            {
               while(i<=n-1)
               {
               arr[i][j]=sum;
               sum++;
               i++;
               j--;                
               }
               j=j+2;    //校正起点
               i--;
               k++;
            }
            if(k % 2 == 0) //斜向上
            {
                while(j<=n-1) 
                {
                    arr[i][j]=sum;
                    sum++;
                    j++;
                    i--;
                }
                i = i+2;   //校正起点
                j--;
                k++;
            }
            if(sum>=n*n)
            {
                break;
            }
        }
        
    }  
  
}
void printf_snake(int arr[1000][1000],int n ) //打印
{
    int i = 0;
    int j = 0;
    for(i=0;i<n;i++)
    {
         for(j=0;j<n;j++)
         {
           printf("%d ",arr[i][j]);
         }
         printf("\n");
    }
}

int main()
{
    int n = 0;
    scanf("%d",&n);
    int arr[1000][1000];
    snake_matrix(arr,n);
    printf_snake(arr,n);
    return 0;
}

发表于 2025-01-03 09:47:11 回复(0)
#include<stdio.h>
int main() {
    int n;
    scanf("%d", &n);
    int array[n + 1][n + 1];
    array[1][1] = 1;
    int i=1, j=1, k=0, pos = 1;
    for (k = 2; k <= n * n; k++) {
        if (i == 1 && j < n && pos == 1) {
            array[i][++j] = k;
            pos = -1;
        } else if (j == 1 && i < n && pos == -1) {
            array[++i][j] = k;
            pos = 1;
        } else if (i == n && pos == -1) {
            array[i][++j] = k;
            pos = 1;
        } else if (j == n && pos == 1) {
            array[++i][j] = k;
            pos = -1;
        } else if (pos == 1) {
            array[--i][++j] = k;
        } else if (pos == -1) {
            array[++i][--j] = k;
        }
    }
    for (i = 1; i <= n; i++) {
        for (j = 1; j <= n; j++)
            printf("%d ", array[i][j]);
        printf("\n");
    }
    return 0;
}

发表于 2024-10-02 19:25:02 回复(0)
n =  int(input())  # map函数用法
arr = [ ['']*n  for _ in range(n)]
i = 0  #  行索引
j = 0  #  列索引
count = 1  # 元素值

arr[i][j] = count # 按蛇形路线确定循环一个周期的的开始

while True:
    # 矩阵最上方只能 右移或下移
    if j+1 < n: # 右移
        j += 1
        count += 1
        arr[i][j] = count
    else :
        if i+1 < n:  # 下移
            i += 1
            count += 1
            arr[i][j] = count
    
    while True:
        if  i+1 < n and 0 <= j-1 : # 左下
            i += 1
            j -= 1
            count += 1
            arr[i][j] = count

        elif  i+1 < n  :  # 全部左下后,能下移一格,则执行
            i += 1
            count += 1
            arr[i][j] = count
            #下移一格后,右上,全部右上后,抵达周期的开始,break结束最近的 while
            for _ in range(i): 
                if 0 <= i-1   and j+1 < n:  # 右上
                    i -= 1
                    j += 1
                    count += 1
                    arr[i][j] = count
            break
            
        elif  j+1 < n:  # 全部左下后,不能下移一格,则判断能否向右一格
            j += 1
            count += 1
            arr[i][j] = count
            #  右上,全部右上后,抵达周期的开始,break结束最近的 while
            for _ in range(i): 
                if 0 <= i-1   and  j+1 < n:  # 右上
                    i -= 1
                    j += 1
                    count += 1
                    arr[i][j] = count
            break
    if i==j and i+1==n:
        break 
for i in arr:
    print(*i)

发表于 2024-09-29 21:00:31 回复(0)
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int[][] nums = new int[n][n];
        int count = 0; //矩阵数字
        int i = 0, j = 0;//i代表行,j代表列
        for (int k = 0; k < n - 1; k++) {   //循环次数n-1次
            int b = j;
            for (i = 0; j < b + 2; j++) {   //一次循环内的横向走向
                if (j < n)
                    nums[i][j] = ++count;
            }
            for (i = 1, j = j - 2; j >= 0; i++, j--) {   //右上到左下走向
                if (i >= 0 && j >= 0 && j < n && i < n)
                    nums[i][j] = ++count;
            }
            for (j = 0; i > 0; i--, j++) {     //左下到右上走向
                if (i >= 0 && j >= 0 && j < n && i < n)
                    nums[i][j] = ++count;
            }
        }
        for (int k = 0; k < n; k++) {
            for (int l = 0; l < n; l++) {
                System.out.print(nums[k][l] + " ");
            }
            System.out.println();
        }
    }
}

发表于 2024-09-07 19:08:35 回复(0)
#include <stdio.h>

int main() {
    int n=0;
    scanf("%d",&n);
    int arr[1001][1001]={0};
    int i=1,j=1,k=0,pos=1;
    arr[i][j]=1;
    for(k=2;k<=n*n;k++)
    {
        if(i==1&&j<n&&pos==1)
        {
            arr[i][++j]=k;
            pos=-1;
        }
        else if(j==1&&i<n&&pos==-1)
        {
            arr[++i][j]=k;
            pos=1;
        }
        else if(j==n&&pos==1)
        {
            arr[++i][j]=k;
            pos=-1;
        }
        else if(i==n&&pos==-1)
        {
            arr[i][++j]=k;
            pos=1;
        }
        else if(pos==1)
        {
            arr[--i][++j]=k;
        }
        else if(pos==-1)
        {
            arr[++i][--j]=k;
        }
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            printf("%d ",arr[i][j]);
        }
        printf("\n");
    }
    return 0;
}

编辑于 2024-04-07 19:48:47 回复(0)
#include <iostream>
using namespace std;

int main() {
    int n;
    cin >> n;
    int num[n][n];
    int count=1;
    // 输出上半部分
    for(int i=0;i<n;i++){
        if(i%2==0){
            int x=i;
            int y=0;
            while(i>=0 && y<=i){
                num[x--][y++]=count++;
            }
        }else{
            int x=0;
            int y=i;
            while(x<=i && y>=0){
                num[x++][y--]=count++;
            }
        }
    }
    //输出下半部分
    if(n%2==0){
        for(int i=1;i<n;i++){
            if(i%2==0){
                int x=i;
                int y=n-1;
                while(x<=n-1 && y>=i){
                    num[x++][y--]=count++;
                }
            }else{
                int x=n-1;
                int y=i;
                while(x>=i && y<=n-1){
                    num[x--][y++]=count++;
                }
            }
        }
    }else{
        for(int i=1;i<n;i++){
            if(i%2==0){
                int y=i;
                int x=n-1;
                while(y<=n-1 && x>=i){
                    num[x--][y++]=count++;
                }
            }else{
                int y=n-1;
                int x=i;
                while(y>=i && x<=n-1){
                    num[x++][y--]=count++;
                }
            }
        }


    }

   // 输出二维数组num
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            cout << num[i][j] << " ";
        }
        cout << endl;
    }
   
    return 0;
}
// 64 位输出请用 printf("%lld")
编辑于 2024-03-25 14:43:59 回复(0)
        在分析坐标下的关系得到的。每一轮的(斜线之内)下表之和是一样的(sum),不算(0,0)一共有2*n-2 轮,分析每一轮i和j的变化就好;sum为偶时,i减j增,为奇时,i加j减。这样就能不断的来给数组赋值。
把每一个轮次的i,j值写出来就很容易看出来规律了。
#include <iostream>
#include<iomanip>
#include<cmath>
#include<string>
using namespace std;

int main() {
    int n;
    cin>>n;
    int a[n][n];
    int count=n*2-2;                //轮次
    int i=0,j=0;        
    int num=1;                      //给i,j赋值用
    int sum=1;                      //表示每一轮的i和j的和
    for (int p=0; p<n; p++) {
        for (int q=0; q<n; q++) {
            a[p][q]=0;                          //全部先赋值为零,方便后面判断break语句
        }
    }
    while (count--) {
        if(i==0&&j==0){                         //(0,0)位置,直接写
            a[i][j]=num;
            j++;
            num++;
        }
        int x=i,y=j;                                        //记录初始状况
        cout<<"x="<<x<<"y="<<y<<endl;           
        while(i+j==sum){
            a[i][j]=num;
            cout<<"num==="<<num<<endl;
            num++;                                          //赋值完就加加
           if(i>=j) {if(x==j&&y==i) break;      //i和j的变化
                       i--;j++;
                       if(a[i][j]!=0){                      //说明已经被赋值过的又来了,例如13,22,31,但是会判断为13,
                                                                        //重复的访问一个,造成死循环,用是否访问过来防止死循环
                        i+=2;j-=2;
                       }
        }
           else    {if(x==j&&y==i) break;                   //一轮结束后,i和j的值一定呼唤
                        j--;i++;
                        if(a[i][j]!=0){
                                    j+=2;i-=2;
                        }
           }                                                             
        }
            cout<<"i="<<i<<"j="<<j<<endl;
        sum++;
        cout<<"sum====="<<sum<<endl;                        //转到下一轮用
        if(sum%2==0&&i==n-1) j++;
        else if(sum%2==1&&j==n-1) i++;                      //达到极限换另一个加
        else if (sum%2==0&&i<n-1) i++;                      
        else if(sum%2==1&&j<n-1) j++;                       //进入下一个轮次的条件,奇偶轮次条件不一样
    }
      for (int p=0;p<n; p++) {
        for (int q=0; q<n; q++) {
            cout<<a[p][q]<<" ";
        }cout<<endl;
    }
}


发表于 2024-03-17 22:06:57 回复(0)
#include <iostream>
#include <bits/stdc++.h>
#include <vector>
using namespace std;

int main() {
    int n;
    cin >> n;
    vector<vector<int>> a(n, vector<int>(n, 0)); //初始全为0的二维数组
    int d = 1; //1表示从左往右,2表示从右上到左下,3表示向下,4表示左下往右上
    int num = 1;
    int top = 0, left = 0;//上下指针和左右指针

    while (num <= n * n) {
        if (d == 1) { //从左往右
            a[top][left++] = num++;
            if (top == n - 1) { //到底了,下一步往右上
                d = 4;
            } else {
                d = 2; //下一步往左下
            }
        } else if (d == 2) { //右上到左下
            a[top++][left--] = num++;
            if (top == n - 1) { //到底了,下一步往右
                d = 1;
            } else if (left == 0) { //到最左边了,下一步往下
                d = 3;
            } else { //继续往左下
                d = 2;
            }
        } else if (d == 3) {
            a[top++][left] = num++;
            if (left == 0) { //左边界往下,下一步往右上
                d = 4;
            } else if (left == n - 1) { //右边界往下,下一步往左下
                d = 2;
            }
        } else if (d == 4) {
            a[top--][left++] = num++;
            if (left == n - 1) {//触碰到右边界,下一步往下
                d = 3;
            } else if (top == 0) { //触碰到上边界,下一步往右
                d = 1;
            } else {
                d = 4;
            }
        }
    }
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            cout << a[i][j] << " ";
        }
        cout << endl;
    }
}
编辑于 2024-03-08 15:56:15 回复(0)