我的任务是让用户输入数字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的元素,并使它们为负值。