4.数组

737. 数组替换

输入一个长度为 10 的整数数组 X[10],将里面的非正整数全部替换为 1,输出替换完成后的数组。

输入格式 输入包含 10 个整数,每个整数占一行。

输出格式 输出新数组中的所有元素,每个元素占一行。

输出格式为 X[i] = x,其中 i 为元素编号(从 0 开始),x 为元素的值。

数据范围 −100≤X[i]≤100 输入样例: 10 -9 0-4 -10 0-2 -7 7 4 输出样例: X[0] = 10 X[1] = 1 X[2] = 1 X[3] = 1 X[4] = 1 X[5] = 1 X[6] = 1 X[7] = 1 X[8] = 7 X[9] = 4

简单判断

#include<cstdio>

using namespace std;

const int N = 12;

int x, a[N];

int main()
{
    for(int i = 0;i < 10;i++)
    {
        scanf("%d", &x);
        if(x <= 0) a[i] = 1;//非正整数
        else a[i] = x;
    }
    for(int i = 0;i < 10;i++) printf("X[%d] = %d\n", i, a[i]);
        
    return 0;
}

条件表达式-压缩代码

#include <iostream>
#include <cstdio>
using namespace std;
int main(){
    for(int i = 0; i < 10; i ++ ){
        int x;  cin >> x;
        printf("X[%d] = %d\n", i, x <= 0 ? 1 : x);
    }
    return 0;
}

738. 数组填充

输入一个整数 V,输出一个长度为 10 的数组 N,数组中的第一个元素为 V,每个后续元素的值都为上一个元素的值的 2 倍。

例如,如果输入整数为 1,则数组为:1,2,4,8… 输入格式 输入一个整数 V。

输出格式 输出数组中的所有元素,每个元素占一行。

输出格式为 N[i] = x,其中 i 为元素编号(从 0 开始),x 为元素的值。

数据范围 1≤V≤50 输入样例: 1 输出样例: N[0] = 1 N[1] = 2 N[2] = 4 N[3] = 8 N[4] = 16 N[5] = 32 N[6] = 64 N[7] = 128 N[8] = 256 N[9] = 512

#include<cstdio>

using namespace std;

typedef long long int LLD;

LLD a[11], v;

int main()
{


    scanf("%lld", &v); //%lld
    for(int i = 0;i < 10;i++)
    {
        a[i] = v;
        v <<= 1; // v *= 2; 
    }

    for(int i = 0;i < 10; i++) printf("N[%d] = %lld\n", i, a[i]);

    return 0;
}

739. 数组选择

输入一个长度为 100 的数组 A,请你按顺序输出其中不大于 10 的所有元素。

输入格式 输入 100 个数,每个数占一行,表示数组的所有元素的值。

每个数可能是整数也可能是浮点数。

输出格式 按顺序输出数组中的所有不大于 10 的元素,每个元素占一行。

输出格式为 A[i] = x,其中 i 为元素编号,x 为元素的值。

注意,所有的 x 均保留一位小数。

数据范围 −100≤A[i]≤100 输入样例: 0-5 63 -8.5 ... 输出样例: A[0] = 0.0 A[1] = -5.0 A[3] = -8.5 ...

#include<cstdio>

using namespace std;

const int N = 105;

double a[N];

int main()
{
    for(int i = 0; i < 100; i++)
    {
        scanf("%lf", &a[i]); //double 用 %d ,则a[i]不会读入数据 
        if(a[i] <= 10.0)
            printf("A[%d] = %.1lf\n", i, a[i]);
    }
    return 0;
}

740. 数组变换

输入一个长度为 20 的整数数组 N,将整个数组翻转,使得第一个元素成为倒数第一个元素,第二个元素成为倒数第二个元素,…,倒数第二个元素成为第二个元素,倒数第一个元素成为第一个元素。

输出翻转后的数组。

输入格式 输入包含 20 个整数,每个数占一行。

输出格式 输出新数组中的所有元素,每个元素占一行。

输出格式为 N[i] = x,其中 i 为元素编号(从 0 开始),x 为元素的值。

数据范围 −100≤N[i]≤100 输入样例: 0-5 ... 63 23 输出样例: N[0] = 23 N[1] = 63 ... N[18] = -5 N[19] = 0

#include <cstdio>
#include<algorithm>
using namespace std;

const int N = 20;

int a[N];

int main()
{
  for(int i = 0; i < 20; i++) scanf("%d", &a[i]);
  //for(int i = 0; i < 20; i++) printf("N[%d] = %d\n", i, a[20 - i - 1]); 下标逆序计算
  reverse(a, a + 20); //函数法
  for(int i = 0; i < 20; i++) printf("N[%d] = %d\n", i, a[i]);

  return 0;
}

old_code

#include <bits/stdc++.h>
using namespace std;
int a[20];
int main()
{
  for(int i=0; i < 20; i++)
  {
    cin>>a[i];
  }
  for(int i = 19; i >=0 ; i--)
  {
    printf("N[%d] = %d\n",abs(i - 19), a[i]);
  }
  return 0;
}

741. 斐波那契数列

输入整数 N,求出斐波那契数列中的第 N 项是多少。

斐波那契数列的第 0 项是 0,第 1 项是 1,从第 2 项开始的每一项都等于前两项之和。

输入格式 第一行包含整数 T,表示共有 T 个测试数据。

接下来 T 行,每行包含一个整数 N。

输出格式 每个测试数据输出一个结果,每个结果占一行,

结果格式为 Fib(N) = x,其中 N 为项数,x 为第 N 项的值。

数据范围 0≤N≤60 输入样例: 3 04 2 输出样例: Fib(0) = 0 Fib(4) = 3 Fib(2) = 1

DP

#include<iostream>

using namespace std;

typedef long long LL; 

const int N = 65;

LL fib[N] = {0,1}; 

int main()
{
    fib[0] = 0, fib[1] = 1;
    for(int i = 2 ; i<= 60 ; i++) fib[i] = fib[i - 1] + fib[i - 2]; 
    int T;
    scanf("%d", &T);
    while(T--)
    {
        int n;
        scanf("%d", &n);
        printf("Fib(%lld) = %lld\n", n, fib[n]);  // LL ~~~~  scanf("%lld", )
        //cout<<"Fib(" << n << ") = "<< fib[n] << endl;
    }
    return 0;
}

递推

#include <cstdio>

using namespace std;

typedef long long LL;

int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        int n;
        scanf("%d", &n);
        LL a = 0, b = 1, c;
        for(int i = 0; i <= n; i++) //递推没有存下来时间复杂度高
        {
          if (i == n) printf("Fib(%d) = %lld\n", n, a); //a从第0项开始,不断往后移动, i从0开始 :a每轮为第i项
          c = a + b;
          a = b;
          b = c;
        }
    }
      return 0;
}

742. 最小数和它的位置

输入一个整数 N 和一个长度为 N 的整数数组 X。

请你找到数组中最小的元素,并输出它的值和下标。

注意,如果有多个最小值,则返回下标最小的那个。

输入格式 第一行包含整数 N。

第二行包含 N 个用空格隔开的整数 X[i]。

输出格式 第一行输出 Minimum value: x,其中 x 为数组元素最小值。

第二行输出 Position: y,其中 y 为最小值元素的下标(下标从 0 开始计数)。

数据范围 1<N≤1000, −1000≤X[i]≤1000 输入样例: 10 1 2 3 4 -5 6 7 8 9 10 输出样例: Minimum value: -5 Position: 4

简版

#include<cstdio>

using namespace std;

const int N = 1010;

int n;
int q[N];

int main()
{
    scanf("%d", &n);
    for(int i = 0; i < n; i++)  scanf("%d", &q[i]);
    
    int minv = 1e4, min_idx;  
    for(int i = 0; i < n; i++)
        if(minv > q[i]) 
        {
            minv = q[i];
            min_idx = i;
        }
    
    printf("Minimum value: %d\nPosition: %d", minv, min_idx);
    
    return 0;
}

容器版

#include<cstdio>
#include<vector>

using namespace std;

int n;
vector<int> q;

int main()
{
    scanf("%d", &n);
    for(int i = 0; i < n; i++)
    {
        int x;
        scanf("%d", &x);
        q.push_back(x); 
    }
    
    int minv = 1e4, min_idx;  
    //for(vector<int>::iterator it = q.begin() ; it != q.end() ; it++)   //不好表示下标:需多一个变量
    int len = q.size();
    for(int i = 0; i < q.size(); i++)
        if(minv > q[i]) 
        {
            minv = q[i];
            min_idx = i;
        }
    
    printf("Minimum value: %d\nPosition: %d", minv, min_idx);
    
    return 0;
}

743. 数组中的行

输入一个二维数组 M[12][12],根据输入的要求,求出二维数组中某一列的元素的平均值或元素的和。

输入格式 第一行输入整数 C,表示所求的具体列数(列数从 0 开始计数)。

第二行包含一个大写字母,若为 S,则表示需要求出第 C 列的元素的和,若为 M,则表示需要求出第 C 列的元素的平均值。

接下来 12 行,每行包含 12 个用空格隔开的浮点数,表示这个二维数组,其中第 i+1 行的第 j+1 个数表示数组元素 M[i][j]。

输出格式 输出一个数,表示所求的平均数或元素的和的值,保留一位小数。

数据范围 −100.0≤M[i][j]≤100.0 输入样例: 1 S -9.0 -2.4 -3.3 2.4 -9.7 -5.7 -5.3 6.5 -7.3 4.8 -4.1 3.9 1.6 -0.9 9.2 -7.5 1.0 -8.0 -4.1 -4.0 -0.1 -9.0 8.4 4.9 -8.2 -0.3 -5.1 -5.6 6.6 0.9 -1.0 -5.4 -2.1 -4.5 -8.7 -1.1 -4.2 6.5 -8.2 3.6 -4.6 -9.2 -1.7 6.9 -9.0 -9.8 7.7 -3.4 -8.0 5.7 4.8 0.3 -1.4 2.8 -6.3 9.3 0.3 6.3 1.5 -1.7 1.7 -0.0 9.7 -6.6 1.3 -2.0 -6.1 2.0 -7.8 -4.7 -9.1 6.0 -8.2 -1.7 9.4 -1.2 -1.0 -9.0 -7.0 -6.9 -1.6 -6.8 -6.7 1.8 4.8 1.3 -6.1 -0.6 0.5 -2.9 -6.8 1.5 5.8 3.2 0.0 7.7 6.3 1.1 4.7 7.3 7.6 5.6 0.9 9.2 1.3 -4.9 7.8 -4.9 0.5 3.5 -5.0 9.0 8.8 8.7 7.5 7.5 -9.6 -6.9 -1.6 6.9 7.8 5.6 -6.4 3.6 2.3 0.5 4.1 6.1 8.6 -9.3 2.2 -0.4 9.9 0.9 6.4 -2.8 -4.2 -7.6 0.6 9.6 3.0 0.9 5.1 4.5 输出样例: 19.3

#include<cstdio>
#include<iostream>

using namespace std;

const int N = 13;

double q[N][N];  //用到精度 : scanf的易错点就来了!!! double ---> %lf ,  LL ---> %lld
double sum[N]; 

int main()
{
    int row; 
    char op;
    //cin >> row >> op; //scanf易错 %d %c
    scanf("%d %c", &row, &op);
    for(int i = 0; i < 12; i++)
        for(int j = 0; j < 12; j++)
        {
            scanf("%lf", &q[i][j]);
            sum[i] += q[i][j]; 
        }
            
    if(op == 'S') printf("%.1lf", sum[row]); //格式输出 printf方便
    else printf("%.1lf", sum[row] / 12);    //压缩代码printf("%.1lf",op=='S' ? sum[row] : sum[row] / 12);
        
    return 0;
}

y总

#include <iostream>
#include <algorithm>

using namespace std;

int main()
{
    int n;
    char op;

    double matrix[12][12];

    cin >> n >> op;
    for (int i = 0; i < 12; i ++ )
        for (int j = 0; j < 12; j ++ )
            cin >> matrix[i][j];

    double s = 0;
    for (int i = 0; i < 12; i ++ ) s += matrix[n][i];

    if (op == 'M') s /= 12;//先求和, 如果求平均就 / 12.0

    printf("%.1lf\n", s);

    return 0;
}


/*简洁版
#include <iostream>

using namespace std;

int main()
{
    int l;
    char op;
    cin >> l >> op;
    double s=0;
    for(int i=0;i<12;i++)
    {
        for(int j=0;j<12;j++)
        {
            double a;
            cin >> a;
            if(i==l) s+=a;
        }
    }

    printf("%.1lf",op=='S' ? s : s/12);
}

*/

744. 数组中的列

输入一个二维数组 M[12][12],根据输入的要求,求出二维数组中某一列的元素的平均值或元素的和。

输入格式 第一行输入整数 C,表示所求的具体列数(列数从 0 开始计数)。

第二行包含一个大写字母,若为 S,则表示需要求出第 C 列的元素的和,若为 M,则表示需要求出第 C 列的元素的平均值。

接下来 12 行,每行包含 12 个用空格隔开的浮点数,表示这个二维数组,其中第 i+1 行的第 j+1 个数表示数组元素 M[i][j]。

输出格式 输出一个数,表示所求的平均数或元素的和的值,保留一位小数。

数据范围 −100.0≤M[i][j]≤100.0 输入样例: 1 S -9.0 -2.4 -3.3 2.4 -9.7 -5.7 -5.3 6.5 -7.3 4.8 -4.1 3.9 1.6 -0.9 9.2 -7.5 1.0 -8.0 -4.1 -4.0 -0.1 -9.0 8.4 4.9 -8.2 -0.3 -5.1 -5.6 6.6 0.9 -1.0 -5.4 -2.1 -4.5 -8.7 -1.1 -4.2 6.5 -8.2 3.6 -4.6 -9.2 -1.7 6.9 -9.0 -9.8 7.7 -3.4 -8.0 5.7 4.8 0.3 -1.4 2.8 -6.3 9.3 0.3 6.3 1.5 -1.7 1.7 -0.0 9.7 -6.6 1.3 -2.0 -6.1 2.0 -7.8 -4.7 -9.1 6.0 -8.2 -1.7 9.4 -1.2 -1.0 -9.0 -7.0 -6.9 -1.6 -6.8 -6.7 1.8 4.8 1.3 -6.1 -0.6 0.5 -2.9 -6.8 1.5 5.8 3.2 0.0 7.7 6.3 1.1 4.7 7.3 7.6 5.6 0.9 9.2 1.3 -4.9 7.8 -4.9 0.5 3.5 -5.0 9.0 8.8 8.7 7.5 7.5 -9.6 -6.9 -1.6 6.9 7.8 5.6 -6.4 3.6 2.3 0.5 4.1 6.1 8.6 -9.3 2.2 -0.4 9.9 0.9 6.4 -2.8 -4.2 -7.6 0.6 9.6 3.0 0.9 5.1 4.5 输出样例: 19.3

浮点数读入

#include<cstdio>

using namespace std;

const int N = 13;

double sum; //浮点数 - 警觉
double q[N][N];

int main()
{
    int n;
    char op;
    scanf("%d %c", &n, &op);
     
    for(int i = 0; i < 12; i++)
        for(int j = 0; j < 12; j++)
        {
            scanf("%lf", &q[i][j]); //浮点数 - 警觉
            if(j == n) sum += q[i][j]; //第n列的和(下标从0开始)
        }
        
    if(op == 'S') printf("%.1lf", sum);
    else printf("%.1lf", sum / 12);
    
    return 0;
}

c++版


#include<bits/stdc++.h>
using namespace std;

int main()
{
    int n,i,j;
    char ch;
    double s,t;
    cin>>n>>ch;
    for(i=0;i<=11;i++)
        for(j=0;j<=11;j++){
            cin>>t;
            if(j==n)s=s+t; //只要j等于n,就累加
        }
    cout<<fixed<<setprecision(1);    
    if(ch=='S') cout<<s;
   	else cout<<s/12;
    //printf("%.1lf", ch == 'S' ? c : c / 12);
	return 0;
}

此类题目写出对角线,就是简单的数学空间区域交集划分

745. 数组的右上半部分

输入一个二维数组 M[12][12],根据输入的要求,求出二维数组的右上半部分元素的平均值或元素的和。

右上半部分是指主对角线上方的部分,如下图所示,黄色部分为对角线,绿色部分为右上半部分:
在这里插入图片描述

输入格式 第一行输入一个大写字母,若为 S,则表示需要求出右上半部分的元素的和,若为 M,则表示需要求出右上半部分的元素的平均值。

接下来 12 行,每行包含 12 个用空格隔开的浮点数,表示这个二维数组,其中第 i+1 行的第 j+1 个数表示数组元素 M[i][j]。

输出格式 输出一个数,表示所求的平均数或元素的和的值,保留一位小数。

数据范围 −100.0≤M[i][j]≤100.0 输入样例: M -6.5 8.2 0.7 9.0 0.8 -4.3 0.9 -0.0 -7.9 7.1 -1.6 4.6 -9.4 -9.0 1.5 -9.0 -5.1 -0.5 -2.8 -9.1 8.0 -6.9 -5.5 -6.6 -6.8 0.3 3.8 6.1 -9.9 -9.3 8.5 8.6 5.0 6.9 -3.6 -3.0 -0.8 -1.6 -7.3 -6.7 4.4 -9.1 -9.0 1.6 0.3 -6.0 6.0 -0.8 -0.8 -6.0 -4.9 -3.9 6.4 6.2 -4.2 -0.9 7.9 1.6 -8.2 -9.2 7.8 -5.8 -5.8 -5.8 7.2 0.5 -7.9 1.2 -6.8 -9.1 0.3 -1.4 4.3 -7.2 3.5 -6.4 -9.1 -6.0 3.5 -5.1 -5.6 -6.9 -9.1 -2.1 -7.6 -7.1 0.7 -1.7 5.0 -9.0 1.4 -6.2 7.6 4.8 -7.5 4.0 -0.2 0.3 -4.2 8.4 0.7 -6.4 -2.7 3.5 -0.9 3.7 0.9 -2.7 7.1 0.1 8.4 -5.1 -7.9 -0.5 -5.3 -5.7 -4.6 9.6 -8.3 7.0 9.6 -9.8 3.3 -9.9 -6.8 6.7 3.1 1.2 -9.5 -4.3 -1.7 -9.7 1.8 5.0 8.3 -0.7 -0.9 3.2 2.5 0.5 7.3 8.3 0.3 0.9 输出样例: -1.2

注意看图【判断与数组下标关系】 在这里插入图片描述 图中绿色求和部分:y > x ----> j > i

绿色部分:==【下标】:倒头看:数组下标对应: y = x分界线(副对角线) , y = -x (正对角线)==

#include<cstdio>

using namespace std;

const int N = 13;
double q[N][N], sum;

int main()
{
    char op;
    scanf("%c\n", &op);
    
    for(int i = 0; i < 12; i++) //一个看图误区:需翻转90度看, 对角线应该为:y = x ---> 右上半部分 : y > x
        for(int j = 0; j < 12; j++)
        {
            scanf("%lf", &q[i][j]);
            if(j > i)  //【下标】:倒头看:数组下标对应: y = x分界线(副对角线)  , y = -x (正对角线)
                sum += q[i][j];
        }
            
    if(op == 'S') printf("%.1lf", sum);
    else printf("%.1lf", sum / 66.0);  //个数  11 * (11 + 1) / 2  
    
       
    return 0;
}

746. 数组的左下半部分

输入一个二维数组 M[12][12],根据输入的要求,求出二维数组的左下半部分元素的平均值或元素的和。

左下半部分是指主对角线下方的部分,如下图所示,黄色部分为对角线,绿色部分为左下半部分:

在这里插入图片描述

输入格式 第一行输入一个大写字母,若为 S,则表示需要求出左下半部分的元素的和,若为 M,则表示需要求出左下半部分的元素的平均值。

接下来 12 行,每行包含 12 个用空格隔开的浮点数,表示这个二维数组,其中第 i+1 行的第 j+1 个数表示数组元素 M[i][j]。

输出格式 输出一个数,表示所求的平均数或和的值,保留一位小数。

数据范围 −100.0≤M[i][j]≤100.0 输入样例: S 8.7 5.6 -2.0 -2.1 -7.9 -9.0 -6.4 1.7 2.9 -2.3 8.4 4.0 -7.3 -2.1 0.6 -9.8 9.6 5.6 -1.3 -3.8 -9.3 -8.0 -2.0 2.9 -4.9 -0.5 -5.5 -0.2 -4.4 -6.1 7.6 6.9 -8.0 6.8 9.1 -8.5 -1.3 5.5 4.6 6.6 8.1 7.9 -9.3 9.6 4.6 0.9 -3.5 -4.3 -7.0 -1.2 7.0 7.1 -5.7 7.8 -2.3 4.3 0.2 -0.4 -6.6 7.6 -3.2 -5.4 -4.7 4.7 3.6 8.8 5.1 -3.1 -2.9 2.8 -4.3 -1.4 -1.8 -3.3 -5.6 1.8 8.3 -0.5 2.0 -3.9 -1.0 -8.6 8.0 -3.3 -2.5 -9.8 9.2 -0.8 -9.4 -0.5 1.6 1.5 3.4 -0.1 7.0 -6.2 -1.0 4.9 2.2 -8.7 -0.9 4.8 2.3 2.0 -3.2 -7.5 -4.0 9.9 -1.1 -2.9 8.7 3.6 7.4 7.8 10.0 -9.0 1.6 8.3 6.3 -5.8 -9.9 0.6 2.0 -3.8 -6.3 0.6 7.3 3.8 -7.1 9.5 2.2 1.3 -2.8 -9.1 7.1 -0.2 0.6 -6.5 1.1 -0.1 -3.6 4.0 -5.4 1.1 输出样例: -2.8

取两个坐标计算直线【副对角线】: y = -x + 11

#include<cstdio>

using namespace std;

const int N = 13;
double q[N][N], sum;

int main()
{
    char op;
    scanf("%c\n", &op);

    for(int i = 0; i < 12; i++) //一个看图误区:需翻转90度看, 对角线应该为:y = x ---> 右上半部分 : y > x
        for(int j = 0; j < 12; j++)
        {
            scanf("%lf", &q[i][j]);
            if(j < -i + 11)  //【下标】:倒头看:数组下标对应: y = x分界线(副对角线)  , y = -x (正对角线)
                sum += q[i][j];
        }

    if(op == 'S') printf("%.1lf", sum);
    else printf("%.1lf", sum / 66.0);  //个数  11 * (11 + 1) / 2  

    return 0;
}

747. 数组的左上半部分

输入一个二维数组 M[12][12],根据输入的要求,求出二维数组的左上半部分元素的平均值或元素的和。

左上半部分是指次对角线上方的部分,如下图所示,黄色部分为对角线,绿色部分为左上半部分:

在这里插入图片描述

输入格式 第一行输入一个大写字母,若为 S,则表示需要求出左上半部分的元素的和,若为 M,则表示需要求出左上半部分的元素的平均值。

接下来 12 行,每行包含 12 个用空格隔开的浮点数,表示这个二维数组,其中第 i+1 行的第 j+1 个数表示数组元素 M[i][j]。

输出格式 输出一个数,表示所求的平均数或和的值,保留一位小数。

数据范围 −100.0≤M[i][j]≤100.0 输入样例: M -0.4 -7.7 8.8 1.9 -9.1 -8.8 4.4 -8.8 0.5 -5.8 1.3 -8.0 -1.7 -4.6 -7.0 4.7 9.6 2.0 8.2 -6.4 2.2 2.3 7.3 -0.4 -8.1 4.0 -6.9 8.1 6.2 2.5 -0.2 -6.2 -1.5 9.4 -9.8 -3.5 -2.3 8.4 1.3 1.4 -7.7 1.3 -2.3 -0.1 -5.4 -7.6 2.5 -7.7 6.2 -1.5 -6.9 -3.9 -7.9 5.1 -8.8 9.0 -7.4 -3.9 -2.7 0.9 -6.8 0.8 -9.9 9.1 -3.7 -8.4 4.4 9.8 -6.3 -6.4 -3.7 2.8 -3.8 5.0 -4.6 2.0 4.0 9.2 -8.9 0.5 -3.9 6.5 -4.3 -9.9 -7.2 6.2 -1.2 4.1 -7.4 -4.6 4.7 -0.4 -2.2 -9.1 0.4 -5.8 9.1 -6.4 9.2 0.7 10.0 -5.7 -9.7 -4.4 4.7 4.7 4.9 2.1 -1.2 -6.2 -8.2 7.0 -5.3 4.9 5.5 7.2 3.4 3.2 -0.2 9.9 -6.9 -6.2 5.1 8.5 7.1 -0.8 -0.7 2.7 -6.0 4.2 -8.2 -9.8 -3.5 7.7 5.4 2.8 1.6 -1.0 6.1 7.7 -6.5 -8.3 -8.5 9.4 输出样例: -0.8

取两个坐标计算直线【副对角线】: y = -x + 11

#include<cstdio>

using namespace std;

const int N = 13;
double q[N][N], sum;

int main()
{
    char op;
    scanf("%c\n", &op);

    for(int i = 0; i < 12; i++) //一个看图误区:需翻转90度看, 对角线应该为:y = x ---> 右上半部分 : y > x
        for(int j = 0; j < 12; j++)
        {
            scanf("%lf", &q[i][j]);
            if(j < -i + 11)  //【下标】:倒头看:数组下标对应: y = x分界线(副对角线)  , y = -x (正对角线)
                sum += q[i][j];
        }

    if(op == 'S') printf("%.1lf", sum);
    else printf("%.1lf", sum / 66.0);  //个数  11 * (11 + 1) / 2  

    return 0;
}

748. 数组的右下半部分

输入一个二维数组 M[12][12],根据输入的要求,求出二维数组的右下半部分元素的平均值或元素的和。

右下半部分是指次对角线下方的部分,如下图所示,黄色部分为对角线,绿色部分为右下半部分:

在这里插入图片描述

输入格式 第一行输入一个大写字母,若为 S,则表示需要求出右下半部分的元素的和,若为 M,则表示需要求出右下半部分的元素的平均值。

接下来 12 行,每行包含 12 个用空格隔开的浮点数,表示这个二维数组,其中第 i+1 行的第 j+1 个数表示数组元素 M[i][j]。

输出格式 输出一个数,表示所求的平均数或和的值,保留一位小数。

数据范围 −100.0≤M[i][j]≤100.0 输入样例: S 9.7 -4.9 6.1 -6.1 -9.6 1.0 -3.2 0.6 3.2 -9.8 4.9 1.2 -2.8 -5.3 2.8 -1.9 -5.4 7.5 -2.0 5.7 2.3 5.3 -7.5 8.9 6.0 4.3 3.8 -6.7 8.1 -0.5 7.8 -2.2 -1.0 4.0 -4.9 -9.4 5.4 3.7 -6.5 -3.9 -3.3 4.1 -2.5 -4.7 8.2 1.4 1.8 4.7 2.4 9.0 -4.3 9.6 8.6 -6.1 -7.4 8.6 5.6 0.5 -0.4 5.2 -5.2 2.9 -5.6 4.0 -0.2 3.8 -4.1 -1.6 -3.8 -3.1 -1.1 3.3 -9.4 -1.4 0.6 6.5 -4.3 -8.3 6.1 2.9 -5.2 2.5 9.8 -7.7 -2.9 -3.6 7.9 -5.8 -4.7 8.2 -6.2 1.0 7.4 -1.0 -4.4 -4.5 0.1 9.5 4.9 1.5 0.8 -8.2 0.4 9.5 -0.8 -0.9 9.7 -2.1 0.1 -7.6 7.8 -6.9 5.5 1.4 4.0 7.8 1.0 -1.2 9.7 -1.9 -4.6 2.3 -5.5 8.2 -4.8 -3.7 5.4 0.2 -2.4 -0.8 7.4 0.0 -0.1 8.2 0.8 -3.5 -7.6 -0.5 5.6 8.4 -8.6 0.9 9.0 -7.5 输出样例: 53.0

#include<cstdio>

using namespace std;

const int N = 13;
double q[N][N], sum;

int main()
{
    char op;
    scanf("%c\n", &op);

    for(int i = 0; i < 12; i++) //一个看图误区:需翻转90度看, 对角线应该为:y = x ---> 右上半部分 : y > x
        for(int j = 0; j < 12; j++)
        {
            scanf("%lf", &q[i][j]);
            if(j > -i + 11)  //【下标】:倒头看:数组下标对应: y = x分界线(副对角线)  , y = -x (正对角线)
                sum += q[i][j];
        }

    if(op == 'S') printf("%.1lf", sum);
    else printf("%.1lf", sum / 66.0);  //个数  11 * (11 + 1) / 2  


    return 0;
}

749. 数组的上方区域

输入一个二维数组 M[12][12],根据输入的要求,求出二维数组的上方区域元素的平均值或元素的和。

数组的两条对角线将数组分为了上下左右四个部分,如下图所示,黄色部分为对角线,绿色部分为上方区域:

在这里插入图片描述

输入格式 第一行输入一个大写字母,若为 S,则表示需要求出上方区域的元素的和,若为 M,则表示需要求出上方区域的元素的平均值。

接下来 12 行,每行包含 12 个用空格隔开的浮点数,表示这个二维数组,其中第 i+1 行的第 j+1 个数表示数组元素 M[i][j]。

输出格式 输出一个数,表示所求的平均数或和的值,保留一位小数。

输出结果与标准答案据对误差不超过 0.1 即视为正确。

数据范围 −100.0≤M[i][j]≤100.0 输入样例: S -4.8 -8.0 -2.9 6.7 -7.0 2.6 6.5 1.7 1.9 5.6 -1.6 -6.3 -4.3 1.5 8.7 -0.3 5.4 -9.3 4.8 7.0 3.6 -8.3 -1.0 1.3 -9.9 9.7 -6.3 5.8 2.9 2.9 -7.7 4.9 -0.6 7.2 6.4 7.7 2.8 -5.8 -0.0 2.2 4.0 7.7 -3.0 -7.5 -3.5 9.7 -4.3 -8.6 -1.8 -0.1 5.4 0.6 9.9 -3.7 -1.1 0.8 -0.2 -0.0 9.9 4.5 3.0 -3.9 2.1 -9.7 5.5 9.4 -4.6 3.3 -9.6 5.1 -4.5 1.5 4.3 -5.4 -7.9 9.2 -7.7 -9.6 -1.5 -1.6 -7.2 2.0 -3.7 -0.7 8.0 2.8 -4.1 7.1 8.4 -5.6 3.9 -9.7 -1.1 3.0 -8.5 -3.3 1.7 5.1 0.1 9.2 4.5 9.7 7.2 8.6 8.7 1.1 6.7 0.3 -3.6 -7.1 -8.9 7.1 -5.9 1.6 -7.4 6.7 3.9 4.3 -2.4 -3.7 8.9 -6.2 5.0 -8.6 -1.3 -8.8 2.6 8.9 5.5 9.0 -2.2 -4.4 5.7 3.7 1.8 -2.1 -7.3 -7.9 4.7 6.0 3.3 -2.8 1.4 -6.9 输出样例: 21.7

上半部 = [右上部&&左上部] : 公共部分 j > i&& j + i < 11 两条对角线 y = x 与 y = -x + 11

#include<cstdio>

using namespace std;

const int N = 13;
double q[N][N], sum;

int main()
{
    char op;
    scanf("%c", &op);
        
    for(int i= 0; i < 12 ; i++)
        for(int j = 0 ;j < 12; j++)
        {
            scanf("%lf", &q[i][j]);
            if(j > i && j < -i + 11) sum += q[i][j]; 
        }
               
    if(op == 'S') printf("%.1lf", sum);           
    else printf("%.1lf", sum / 30); // (10 + 2) * 5 / 2 == 30
               
    return 0;
}

750. 数组的下方区域

输入一个二维数组 M[12][12],根据输入的要求,求出二维数组的下方区域元素的平均值或元素的和。

数组的两条对角线将数组分为了上下左右四个部分,如下图所示,黄色部分为对角线,绿色部分为下方区域:

在这里插入图片描述

输入格式 第一行输入一个大写字母,若为 S,则表示需要求出下方区域的元素的和,若为 M,则表示需要求出下方区域的元素的平均值。

接下来 12 行,每行包含 12 个用空格隔开的浮点数,表示这个二维数组,其中第 i+1 行的第 j+1 个数表示数组元素 M[i][j]。

输出格式 输出一个数,表示所求的平均数或和的值,保留一位小数。

数据范围 −100.0≤M[i][j]≤100.0 输入样例: S -6.0 0.7 -8.4 -5.7 -4.1 7.6 9.5 -9.7 4.1 0.6 -6.5 -4.9 6.6 4.9 -3.1 5.3 0.3 -4.5 3.9 -1.5 6.6 7.0 5.1 2.5 -8.5 1.8 -2.7 0.1 -4.9 -7.2 4.3 6.0 -1.4 2.7 -3.0 2.0 4.8 -7.0 -1.3 0.8 1.0 4.5 -1.1 -2.9 -3.9 -3.9 -8.9 5.8 -2.1 -9.6 5.1 0.2 1.0 -1.7 6.4 4.1 2.8 -6.9 2.4 9.3 -6.0 -9.1 -7.0 -7.0 7.8 5.1 6.9 -7.6 0.4 -7.2 5.5 6.0 -1.9 5.5 1.9 -8.5 -5.3 2.3 -9.3 2.0 -0.2 1.2 5.6 -1.8 8.2 2.3 3.5 1.4 4.0 -5.1 -6.9 -2.8 1.7 -7.0 7.8 1.8 -6.0 -4.1 -4.6 -9.4 -4.9 -4.1 4.2 6.3 -2.8 8.7 8.1 -0.9 8.8 -6.5 -4.3 6.1 -6.2 -3.9 -7.0 7.3 5.0 -0.9 -0.0 5.6 -2.4 1.4 8.5 -2.2 0.9 5.3 3.6 8.8 -8.1 3.0 -3.1 6.5 -3.8 -6.4 2.3 4.2 -9.8 -0.3 -9.9 -7.4 3.5 1.5 -0.2 7.0 输出样例: -11.9

#include<cstdio>

using namespace std;

const int N = 13;
double q[N][N], sum;

int main()
{
    char op;
    scanf("%c", &op);
        
    for(int i= 0; i < 12 ; i++)
        for(int j = 0 ;j < 12; j++)
        {
            scanf("%lf", &q[i][j]);
            if(j < i && j > -i + 11) sum += q[i][j]; 
        }
               
    if(op == 'S') printf("%.1lf", sum);           
    else printf("%.1lf", sum / 30); 
               
    return 0;
}

751. 数组的左方区域

输入一个二维数组 M[12][12],根据输入的要求,求出二维数组的左方区域元素的平均值或元素的和。

数组的两条对角线将数组分为了上下左右四个部分,如下图所示,黄色部分为对角线,绿色部分为左方区域:

在这里插入图片描述

输入格式 第一行输入一个大写字母,若为 S,则表示需要求出左方区域的元素的和,若为 M,则表示需要求出左方区域的元素的平均值。

接下来 12 行,每行包含 12 个用空格隔开的浮点数,表示这个二维数组,其中第 i+1 行的第 j+1 个数表示数组元素 M[i][j]。

输出格式 输出一个数,表示所求的平均数或和的值,保留一位小数。

数据范围 −100.0≤M[i][j]≤100.0

mycode2022

#include<cstdio>

using namespace std;

const int N = 13;
double q[N][N], sum;

int main()
{
    char op;
    scanf("%c", &op);
        
    for(int i= 0; i < 12 ; i++)
        for(int j = 0 ;j < 12; j++)
        {
            scanf("%lf", &q[i][j]);
            if(j < i && j < -i + 11) sum += q[i][j]; 
        }
               
    if(op == 'S') printf("%.1lf", sum);           
    else printf("%.1lf", sum / 30); 
               
    return 0;
}

哈夫曼距离


#include<cstdio>
#include<cmath>
int main(){
    char a;
    scanf("%c", &a);
    double n[15][15];
    for(int i = 0; i <12 ;i++){
        for(int j = 0; j < 12; j++){
            scanf("%lf", &n[i][j]);
        }
    }
    double sum = 0;
    int c = 0;  //加计数器,不用自己算平均数分母
    for(int i = 0; i < 12; i++){
        for(int j = 0; j < 12; j++){
            if((abs(5.5-i)+j) <= 4.5){   //麦哈顿距离  (比较不好想)
                sum += n[i][j];
                c++;  
            }

        }
    }
    if(a == 'S') printf("%.1lf", sum);
    else printf("%.1lf", sum / c);
    return 0;
}

==法二:等效上半部矩阵转置【i,j互换位置】==


#include<bits/stdc++.h>
using namespace std;

char c;
double a[13][13],sum;
int main()
{
    scanf("%c\n",&c);

    for(int i = 0;i < 12;i++)
        for(int j = 0;j < 12;j++)
        {
            scanf("%lf",&a[i][j]);   //数组的左方区域:(i+j)<11 && i>j                             【左上 - 上半 - 交集中的对角线】
            if( i + j < 11 && i > j  )                                                           //不正确.. i < 11 && (j > i && j + i < 11) && j != i + 11
                sum += a[i][j];
        }

    if(c == 'S') printf("%.1lf",sum);
    else printf("%.1lf",sum/30);  // 与上半部分相同个数

    return 0;
}

曼尔顿距离用法【斜线适用 y = x或 -x + b】 ①(边界斜线或对角线交点):起点坐标(x1,y1) 与(i,j)
② |x1-x2| + |y1-y2| <= distance (等于看边界是否可取)

752. 数组的右方区域

输入一个二维数组 M[12][12],根据输入的要求,求出二维数组的右方区域元素的平均值或元素的和。

数组的两条对角线将数组分为了上下左右四个部分,如下图所示,黄色部分为对角线,绿色部分为右方区域:

在这里插入图片描述

输入格式 第一行输入一个大写字母,若为 S,则表示需要求出右方区域的元素的和,若为 M,则表示需要求出右方区域的元素的平均值。

接下来 12 行,每行包含 12 个用空格隔开的浮点数,表示这个二维数组,其中第 i+1 行的第 j+1 个数表示数组元素 M[i][j]。

输出格式 输出一个数,表示所求的平均数或和的值,保留一位小数。

数据范围 −100.0≤M[i][j]≤100.0 输入样例: S 2.4 7.8 9.4 -5.6 6.9 -4.9 4.8 0.8 3.6 1.7 -1.4 9.7 -6.8 -3.7 -2.0 -4.9 -4.5 -5.3 6.1 7.5 -4.3 5.9 -9.5 9.7 -6.5 -0.4 1.6 3.7 -4.4 -3.3 1.9 7.7 -1.4 4.5 7.4 -3.0 -1.2 0.4 9.8 9.8 -4.3 -1.3 -1.6 0.5 2.8 -4.0 8.5 3.9 0.2 -2.0 -6.4 -9.8 3.7 -2.0 1.7 -3.6 -3.4 2.4 -1.2 -3.9 -8.3 5.8 -1.0 -4.4 1.0 -2.4 2.8 -4.6 2.1 8.7 -6.8 -8.3 6.3 -6.8 -7.0 9.3 -7.7 -1.7 8.2 -6.5 -1.8 6.7 8.2 4.4 0.4 8.6 -1.2 8.6 -4.6 1.8 9.6 1.6 2.0 -1.0 3.9 -9.2 7.5 -3.1 6.2 -4.5 -3.0 2.5 -7.7 2.9 0.3 3.3 -2.7 3.4 -5.0 3.0 -0.0 4.3 9.5 -0.0 -9.9 -8.6 -0.9 -5.5 7.7 6.5 4.9 -9.6 -2.9 8.5 2.0 -9.9 -4.9 -1.5 -2.4 -7.6 1.7 8.5 -6.4 6.8 -3.7 -4.7 0.2 5.8 -5.4 0.6 7.0 -4.2 -7.5 -2.4 输出样例: 40.9

753. 平方矩阵 I

输入整数 N,输出一个 N 阶的回字形二维数组。

数组的最外层为 1,次外层为 2,以此类推。

输入格式 输入包含多行,每行包含一个整数 N。

当输入行为 N=0 时,表示输入结束,且该行无需作任何处理。

输出格式 对于每个输入整数 N,输出一个满足要求的 N 阶二维数组。

每个数组占 N 行,每行包含 N 个用空格隔开的整数。

每个数组输出完毕后,输出一个空行。

数据范围 0≤N≤100 输入样例: 1 2 3 4 5 0输出样例: 1

1 1 1 1

1 1 1 1 2 1 1 1 1

1 1 1 1 1 2 2 1 1 2 2 1 1 1 1 1

1 1 1 1 1 1 2 2 2 1 1 2 3 2 1 1 2 2 2 1 1 1 1 1 1

写的不错

规律:四个方向到自身的最短距离

#include<iostream>

using namespace std;

int main()
{
    int n;
    while(scanf("%d", &n) && n)
    {
        for(int i = 0; i < n; i++)
        {
            for(int j = 0; j < n; j++) //复合简写:min(min(i + 1, j + 1), min(n - i, n - j)) 
            {
                int x = min(i + 1, n - i); //选取x
                int y = min(j + 1, n - j); // 选取y
                int z = min(x, y); //选取最短
                printf("%d ", z);
            }
            puts("");
        }
        puts("");
    }
    return 0;
}

Chuckie写的很棒 曼哈顿距离法

①当n为奇数时, 找取中间点n / 2分别于行i列j的距离的最大值(max(abs(n / 2 - i), abs(n / 2 - j))),可以的如下图形(例如n == 5): 2 2 2 2 2 2 1 1 1 2 2 1 0 1 2 2 1 1 1 2 2 2 2 2 2 ②观察结果, 随着回形越深入,内外围回形相差为1, 因此想到 (n + 1) / 2 ③当n为偶数时,采用同样的方法, 这里我们就让中心点在图形的中间位置 (n - 1) / 2.0, 再求解其分别于行i列j的距离的最大值(max(abs((n - 1) / 2.0 - i), abs((n - 1) / 2.0 - j))) ④再考虑所得图形与实际结果相差值,这里我们依然设置(n + 1) / 2

#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

int main()
{
    int n;
    int a[100][100];

    while (cin >> n, n)   
    {
        for (int i = 0; i < n; i ++ )
            for (int j = 0; j < n; j ++ )
            {
                if (n % 2) //n为奇数 
                {
                    a[i][j] = (n + 1) / 2 - max(abs(i - n / 2), abs(j - n / 2));     //中心点 (n / 2, n / 2 )
                }
                else //n为偶数 
                {
                    a[i][j] = n / 2 - max(min(abs(i - n / 2), abs(i - (n - 1) / 2)), min(abs(j - n / 2), abs(j - (n - 1) / 2)));
                }
            }

        for (int i = 0; i < n; i ++ )
        {
            for (int j = 0; j < n; j ++ ) printf("%d ", a[i][j]);
            puts("");
        }
        puts("");
    }
    return 0;
}

利用蛇形矩阵求解

①设置一个计数器统计方向改变次数 ②设置变量res表示回形当前圈数 ③其他部分与蛇形矩阵相同


#include <iostream>
#include <cstring>
#include <cmath>

using namespace std;

const int N = 100 + 10;
int m[N][N];

int main(){
    int n;
    int dx[] = {-1, 0, 1, 0}, dy[] = {0, 1, 0, -1};

    while(cin >> n, n ){
        memset(m, 0, sizeof m);
        int d = 1, x = 0, y = 0;
        int cnt = 0;  // 表示改变方向次数
        int res = 1;  // 回形当前圈数
        for (int i = 0; i < n * n; i ++){
            int a = x + dx[d], b = y + dy[d];
            m[x][y] = res;

            if (a < 0 || a >= n || b < 0 || b >= n || m[a][b]){
                d = (d + 1) % 4;
                a = x + dx[d], b = y + dy[d];
                cnt ++;
                if (!(cnt % 4)) res ++;
            }
            x = a, y = b;
        }

        for (int i = 0; i < n; i ++){
            for (int j = 0; j < n; j ++)
                cout << m[i][j] << ' ';
            cout << endl;
        }
        cout << endl;
    }

    return 0;
}

754. 平方矩阵 II

输入整数 N,输出一个 N 阶的二维数组。

数组的形式参照样例。

输入格式 输入包含多行,每行包含一个整数 N。

当输入行为 N=0 时,表示输入结束,且该行无需作任何处理。

输出格式 对于每个输入整数 N,输出一个满足要求的 N 阶二维数组。

每个数组占 N 行,每行包含 N 个用空格隔开的整数。

每个数组输出完毕后,输出一个空行。

数据范围 0≤N≤100 输入样例: 1 2 3 4 5 0输出样例: 1

1 2 2 1

1 2 3 2 1 2 3 2 1

1 2 3 4 2 1 2 3 3 2 1 2 4 3 2 1

1 2 3 4 5 2 1 2 3 4 3 2 1 2 3 4 3 2 1 2 5 4 3 2 1

法一:每次向右延伸和向下延伸看在这里插入图片描述

规律:每轮从(i, i)开始往右和往下单调递增填

#include<cstdio>

using namespace std;

const int N = 105;

int n;
int q[N][N];

int main()
{
    while(scanf("%d\n",&n), n)
    {
        for(int i = 0; i < n; i++)   
        {
            for(int j = i,k = 1; j <= n; j++, k++) //每轮都需从k = 1开始  , j = i 开始(不要覆盖之前填的)
            {
                q[i][j] = k; //向右延伸   
                q[j][i] = k; //向下延伸
            }
            
        }
        for(int i = 0; i < n; i++)
        {
            for(int j = 0; j < n; j++)
            {
                printf("%d ",q[i][j]); 
            }
            puts("");
        }
        puts("");
    }
    
    return 0;
}

法二:正对角线(i, i)分界:左半向中间递增,右半递减填写每行 每行看:对角线前递增,对角线后递减 (不用数组,直接输出)

#include<cstdio>

using namespace std;

int n;

int main()
{
    while(scanf("%d\n",&n), n)
    {
        for(int i = 1;i <= n; i++)
        {
            for(int j = i; j >= 1; j--) printf("%d ",j);
            for(int j = i + 1; j <= n; j++) printf("%d ",j - i + 1);  //【从1开始时】
            puts("");
        }
        puts("");
    }
    
    return 0;
}

在这里插入图片描述 法三:下标与值规律

#include<cstdio>

using namespace std;

int n;

int main()
{
    while(scanf("%d\n",&n), n)
    {
        for(int i = 1; i <= n; i++)
        {
            for(int j = 1; j < n; j++)
                printf("%d ", abs(j - i) + 1);  //【从1开始时,从0开始一样:|i-j|不变】
            puts("");
        }
         puts("");
    }
    
    return 0;
}

其他法:还可以当作对称矩阵解题:上三角 = 下三角 对称 值相等

755. 平方矩阵 III

输入整数 N,输出一个 N 阶的二维数组 M。

这个 N 阶二维数组满足 M[i][j]=2i+j。

具体形式可参考样例。

输入格式 输入包含多行,每行包含一个整数 N。

当输入行为 N=0 时,表示输入结束,且该行无需作任何处理。

输出格式 对于每个输入整数 N,输出一个满足要求的 N 阶二维数组。

每个数组占 N 行,每行包含 N 个用空格隔开的整数。

每个数组输出完毕后,输出一个空行。

数据范围 0≤N≤15 输入样例: 1 2 3 4 5 0输出样例: 1

1 2 2 4

1 2 4 2 4 8 4 8 16

1 2 4 8 2 4 8 16 4 8 16 32 8 16 32 64

1 2 4 8 16 2 4 8 16 32 4 8 16 32 64 8 16 32 64 128 16 32 64 128 256

位运算:【 1 << (i + j)】

#include <cstdio>

using namespace std;

int main()
{
    int n;

    while (scanf("%d", &n), n)
    {
        for (int i = 0; i < n; i ++ )
        {
            for (int j = 0; j < n; j ++ )
            {
                printf("%d ", 1 << (i + j));    //用位运算表示2的幂运算  【超快】
            }
            puts("");
        }
        puts("");
    }

    return 0;
}

改造平方矩阵Ⅱ

#include<cstdio>

using namespace std;

const int N = 105;

int n;
int q[N][N];

int main()
{
    while(scanf("%d\n",&n),n)
    {
        for(int i = 0;i < n;i++)   
        {
            for(int j = i,k = 1 << (i + j);j < n; j++ , k <<= 1) //i,j从0开始:每轮从k = 2^(i + j)开始 ; k *= 2
            {
                q[i][j] = k; //向右延伸   
                q[j][i] = k; //向下延伸
            }
            
        }
        for(int i = 0; i < n; i++)
        {
            for(int j = 0;j < n;j++)
            {
                printf("%d ",q[i][j]); 
            }
            puts("");
        }
        puts("");
    }
    
    return 0;
}

下标与值规律 (按i行从1开始)-----> $2 ^ i * 2 ^ j == 2 ^ {i + j}$


#include<bits/stdc++.h>
using namespace std;

int n,t;
int main()
{
    while(scanf("%d\n",&n),n)
    {
        for(int i = 0;i < n;i++)
        {
            for(int j = 0;j < n;j++)
            {   
                t = 1;
                for(int k = 0;k < i + j ; k ++)
                {
                    t *= 2;
                }
                printf("%d ",t);  //  2^(i+j)     
            }
                
            printf("\n");
        }
        
         printf("\n");
    }
    
    return 0;
}




*756. 蛇形矩阵

输入两个整数 n 和 m,输出一个 n 行 m 列的矩阵,将数字 1 到 n×m 按照回字蛇形填充至矩阵中。

具体矩阵形式可参考样例。

输入格式 输入共一行,包含两个整数 n 和 m。

输出格式 输出满足要求的矩阵。

矩阵占 n 行,每行包含 m 个空格隔开的整数。

数据范围 1≤n,m≤100 输入样例: 3 3 输出样例: 1 2 3 8 9 4 7 6 5

向量枚举法

d与dx和dy初始值会影响输出结果!!!

#include<iostream>

using namespace std;

const int N = 110;

int n,m;
int q[N][N];

int main()
{
    scanf("%d%d",&n,&m);
    int dx[] = {-1,0,1,0} , dy[] = {0,1,0,-1};//固定风格写:-1开始-1结束
    int x = 0,y = 0,d = 1;// d用于方向选择 1, 2, 3, 0 【上右下左】 d与dx和dy初始值会影响输出结果!!!
    //DFS搜索 【注意方向向量必须先判断右到不能走再往下走,再判断左, 再判断上(即此题固定右下左上)】
    for(int i = 1;i <= n * m;i++)   //【用i赋值且遍历n*m格 】
    {
        q[x][y] = i; //赋值:每轮填i
        int a = x + dx[d], b = y + dy[d];
        if(a < 0 ||a >= n || b < 0 || b >= m || q[a][b])  //【出界或(a,b)已填过不能走,判断下一个方向】 
        {
            d = (d+1) % 4;//判断下一个方向  【方向循环*妙*】
            a = x + dx[d], b = y + dy[d];
        }
        x = a ,y = b; // 新起点
    }
    
    for(int i = 0;i < n;i++)
    {
        for(int j = 0;j < m;j++)
        {
            printf("%d ",q[i][j]);            
        }
        puts("");
    }
    
    return 0;
}
/*

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 110;

int n, m;
int a[N][N];

void print2D(int x, int y, int val, int dir)
{
    if (val == n * m) return;
        
    switch(dir){
        case 0:
            while (a[x][y + 1] == 0)
                y ++, val ++, a[x][y] = val;
            print2D(x, y, val, 1);
            break;
        case 1:
            while (a[x + 1][y] == 0)
                x ++, val ++, a[x][y] = val;
            print2D(x, y, val, 2);
            break;
        case 2:
            while (a[x][y - 1] == 0)
                y --, val ++, a[x][y] = val;
            print2D(x, y, val, 3);
            break;
        case 3:
            while (a[x - 1][y] == 0)
                x --, val ++, a[x][y] = val;
            print2D(x, y, val, 0);
            break;
    }
}

int main()
{
    cin >> n >> m;
    for (int i = 0; i <= n + 1; i ++ )
        a[i][0] = a[i][m + 1] = -1;
    for (int j = 0; j <= m + 1; j ++ )
        a[0][j] = a[n + 1][j] = -1;
    print2D(1, 0, 0, 0);
    for (int i = 1; i <= n; i ++ ){
        for (int j = 1; j <= m; j ++ )
            cout << a[i][j] << ' ';
        cout << endl;
    }
    return 0;
}
*/

/*
#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 110;

int n, m, a[N][N];

bool check(int x, int y){
    return x > 0 && x <= n && y > 0 && y <= m;
}

int main()
{
    cin >> n >> m;
    int x = 1, y = 0, val = 0;
    while (val != n * m)
    {
        while (check(x, y + 1) && a[x][y + 1] == 0)
            ++ y, ++ val, a[x][y] = val;
        while (check(x + 1, y) && a[x + 1][y] == 0)
            ++ x, ++ val, a[x][y] = val;
        while (check(x, y - 1) && a[x][y - 1] == 0)
            -- y, ++ val, a[x][y] = val;
        while (check(x - 1, y) && a[x - 1][y] == 0)
            -- x, ++ val, a[x][y] = val;
    }
    for (int i = 1; i <= n; i ++ )
    {
        for (int j = 1; j <= m; j ++ )
            cout << a[i][j] << ' ';
        cout << endl;
    }
    return 0;
}

*/