不知道如何在矩阵中将"under the diagonal"数字更改为负数



我的任务是让用户输入数字n,然后生成维度为n*n的矩阵。然后,程序使对角线上的数字为0,对角线上的数字必须为正数(1,2,…,n),对角线下的数字必须为负数(-1,-2,…,-n)。经过8个小时的思考,我成功地制作出了矩阵,但是对角线下面的数字应该是负的,却是正的。我找不到问题在哪里。

输入样例:

Enter n: 5
Matrix:
0   1   2   3   4
-1   0   1   2   3
-2  -1   0   1   2
-3  -2  -1   0   1
-4  -3  -2  -1   0
我输出:

Enter n: 5
Matrix:
0   1   2   3   4
1   0   1   2   3
2   1   0   1   2
3   2   1   0   1
4   3   2   1   0

我代码:

#include <bits/stdc++.h>
using namespace std;
void solve(long long n)
{
long long array1[n - 1][n - 1], array2[n][n];

for (long long i = 0; i < n - 1; ++i)
array1[0][i] = i + 1;

for (long long i = 1; i < n - 1; ++i)
for (long long j = 0; j < n - 1; ++j)
array1[i][j]
= array1[i - 1][(j + 1) % (n - 1)];

for (long long i = 0; i < n - 1; ++i)
for (long long j = 0; j < n - 1; ++j)
array2[i][j] = array1[i][j];
for (long long i = 0; i < n; ++i)
array2[i][n - 1] = array2[n - 1][i] = 0;
for (long long i = 0; i < n; ++i) {
long long t0 = array2[i][i];
long long t1 = array2[i][n - 1];

swap(array2[i][i], array2[i][n - 1]);

array2[n - 1][i] = t0;
}
for (long long i = 0; i < n; ++i) {
for (long long j = 0; j < n; ++j)
cout << array2[i][j] << " ";
cout << endl;
}
}

int main()
{
long long n = 5;
solve(n);

return 0;
}

根据我的评论,关键是找到一个可以利用的模式。我们也将偏离c数组,不仅仅是因为推荐向量的SO meme,即使它不相关,但因为它们实际上是这个用例中更好的数据结构。

您最终使用vla或变长数组。它们不是c++的一部分,而是C的可选的部分。对vla的支持可能随时消失,最重要的是,正如另一条注释中提到的,它们对堆栈不安全。

在我们进入解决方案之前,我应该处理您的前两行代码。每一行都有一个答案,告诉你为什么它们不好:

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

那么,这个神奇的模式是什么?我选择单独看一行。在通过正方形2D数组的典型嵌套for循环迭代中,当行号等于列号时出现对角线。如果i是用于迭代行的变量,则对角线落在matrix[i][i]上。

模式用于检查一行的值。左边的值应该是负值,右边的值应该是正值。不仅如此,这些值还应该是到对角线元素的距离。

好吧,如果我使用j作为我的列计数器,值就像j - i一样简单。考虑第二行i = 1

-1 0 1 2 3

这是第1行,所以[1][1]是第0元素。在[1][0],j - i== -1,以此类推。查找模式极大简化您需要编写的代码。下面是一个实现:

#include <cstdlib>
#include <iomanip>
#include <iostream>
#include <vector>
void solve(const long long n) {
// Declare and zero-initialize
std::vector<std::vector<int>> v(n, std::vector<int>(n, 0));
// Fill array
for (std::size_t i = 0; i < v.size(); ++i) {
for (std::size_t j = 0; j < v[i].size(); ++j) {
v[i][j] = static_cast<int>(j) - static_cast<int>(i);
}
}
// Find length of biggest number, v[0][n - 1]; for printing purposes
int largest = v[0][n - 1];
int numLength = 0;
while (largest != 0) {
++numLength;
largest /= 10;
}
// Print array
for (auto i : v) {
for (auto j : i) {
std::cout << std::setw(numLength + 2) << j << ' ';
}
std::cout << 'n';
}
}
int main(int argc, char* argv[]) {
if (argc != 2) return 1;
long long n = std::atoi(argv[1]);
solve(n);
}

示例输出:

❯ ./a.out 5
0   1   2   3   4 
-1   0   1   2   3 
-2  -1   0   1   2 
-3  -2  -1   0   1 
-4  -3  -2  -1   0 
❯ ./a.out 15
0    1    2    3    4    5    6    7    8    9   10   11   12   13   14 
-1    0    1    2    3    4    5    6    7    8    9   10   11   12   13 
-2   -1    0    1    2    3    4    5    6    7    8    9   10   11   12 
-3   -2   -1    0    1    2    3    4    5    6    7    8    9   10   11 
-4   -3   -2   -1    0    1    2    3    4    5    6    7    8    9   10 
-5   -4   -3   -2   -1    0    1    2    3    4    5    6    7    8    9 
-6   -5   -4   -3   -2   -1    0    1    2    3    4    5    6    7    8 
-7   -6   -5   -4   -3   -2   -1    0    1    2    3    4    5    6    7 
-8   -7   -6   -5   -4   -3   -2   -1    0    1    2    3    4    5    6 
-9   -8   -7   -6   -5   -4   -3   -2   -1    0    1    2    3    4    5 
-10   -9   -8   -7   -6   -5   -4   -3   -2   -1    0    1    2    3    4 
-11  -10   -9   -8   -7   -6   -5   -4   -3   -2   -1    0    1    2    3 
-12  -11  -10   -9   -8   -7   -6   -5   -4   -3   -2   -1    0    1    2 
-13  -12  -11  -10   -9   -8   -7   -6   -5   -4   -3   -2   -1    0    1 
-14  -13  -12  -11  -10   -9   -8   -7   -6   -5   -4   -3   -2   -1    0 

很明显,当我们能够利用模式而不是强制使用模式时,solve()函数会变得简单得多。

只需在嵌套的for循环中添加一个条件,检查index_of_row大于index_of_column的元素,并使它们为负值。

最新更新