题目
输入矩阵规模N,输出zigzag矩阵。
zigzag顺序为下图所示
输入
5
输出
0 1 5 6 14
2 4 7 13 15
3 8 12 16 21
9 11 17 20 22
10 18 19 23 24
解析1
此方法是计算顺序位置的对应元素值。
假定i为行数,j为列数,每一条斜线下标(i+j)为常数,记为s(s=i+j)。
处理分为上三角和下三角两部分处理。
对于上三角,每一个斜线上的元素个数比上一斜线多一个,每个斜线上的第一个元素表示了该斜线之前元素的个数。运用等差数列求和公式,则每一斜线第一个元素的值为(1 + s) * s / 2。奇数斜线上,元素是向右上递增的,其上任意元素可以表示为s*(s+1)/2+j,而偶数斜线上任意元素可以表示为s*(s+1)/2+i。
对于下三角,斜线上元素的个数是递减的。反过来看可以看成是递增的,就仍然可以套用等差数列求和公式,求出剩下的元素的个数,用总元素个数减去剩下的元素个数就是当前斜线上的第一个元素值。所有元素的个数是n*n,剩下的元素个数为m * (m + 1) / 2,其中m=(n-1-i)+(n-1-j)。则该斜线的第一个元素值为n*n - m*(m+1)/2。
代码1
#include <iostream>
#include <iomanip>
#include <vector>
using namespace std;
int main()
{
int N;
cin >> N; //
vector<int> vec(N*N);
int s,m,smax = N * N;
for(int i = 0; i < N; i++)
{
for(int j = 0; j < N; j++)
{
s = i + j;
if(s < N)
{
vec[i * N + j] = s * (s + 1) / 2 + ((s % 2 == 0) ? j : i);
}
else
{
m = (N - 1 - i) + (N - 1 - j);
vec[i * N + j] = smax - m * (m + 1) / 2 - (N - ((s % 2 == 0) ? j : i));
}
}
}
for(int i = 0; i < N; i++)
{
for(int j = 0; j < N; j++)
{
cout << setw(4) << vec[i * N + j];
}
cout << endl;
}
return 0;
}
解析2
此方法是寻找顺序元素的对应位置
zigzag矩阵中的任意元素m[i][j]的遍历走向规律分为边界走向和非边界走向
非边界走向
非边界走向情况比较简单,如果二维数组中的元素m[i][j]的横纵坐标和i+j是偶数,则遍历路径在矩阵中的走向就是右上角移动一格;否则,若i+j是奇数,则遍历路径在矩阵中的走向就是左下角移动一格。
边界走向
N为奇数时,分为上下两个三角矩阵
上三角矩阵
如果二维数组中的元素m[i][j]中坐标j是偶数,那么遍历路径在矩阵中的走向就是水平向右移动一格。
如果二维数组中的元素m[i][j]中坐标i是奇数,那么遍历路径在矩阵中的走向就是垂直向下移动一格。
下三角矩阵
如果二维数组中的元素m[i][j]中坐标j是奇数,那么遍历路径在矩阵中的走向就是水平向右移动一格。
如果二维数组中的元素m[i][j]中坐标i是偶数,那么遍历路径在矩阵中的走向就是垂直向下移动一格。
N为偶数时,
如果二维数组中的元素m[i][j]中坐标j是偶数,且i=0或者i=7,那么遍历路径在矩阵中的走向就是水平向右移动一格。
如果二维数组中的元素m[i][j]中坐标i是奇数,且j=0或者j=7,那么遍历路径在矩阵中的走向就是垂直向下移动一格。
代码2
#include <iostream>
#include <iomanip>
#include <vector>
using namespace std;
int main()
{
int N;
cin >> N;
vector<int> vec(N*N);
int x=0, y=0;
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
vec[x * N + y] = i * N +j;
//边界转向分为奇偶两种情况
//奇数情况分为上下三角进行处理
if(N % 2)
{
//上三角
if ((x + y) < N - 1)
{
if (x == 0 && y % 2 == 0 )
{
y++;
continue;
}
if (y == 0 && x % 2 == 1 )
{
x++;
continue;
}
}
//下三角
else
{
if (x == N - 1 && y % 2 == 1 )
{
y++;
continue;
}
if (y == N - 1 && x % 2 == 0 )
{
x++;
continue;
}
}
}
//偶数情况可以直接处理
else
{
if ((x == N - 1 || x == 0) && y % 2 == 0 )
{
y++;
continue;
}
if ((y == N - 1 || y == 0) && x % 2 == 1 )
{
x++;
continue;
}
}
//非边界处理
if ((x + y) % 2 == 0)
{
x--;
y++;
}
else
{
x++;
y--;
}
}
}
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
cout << setw(4) << vec[i * N + j];
}
cout << endl;
}
return 0;
}