GEEK编程练习— —zigzag矩阵

题目

输入矩阵规模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;
}
时间: 2024-10-10 14:39:27

GEEK编程练习— —zigzag矩阵的相关文章

C++生成zigzag矩阵

// test_max.cpp : 定义控制台应用程序的入口点. #include "stdafx.h" #include <iostream> using namespace std; #define N 8 int main() { int** A=(int **)malloc(N*sizeof(int*)); for(int i=0;i<N;i++) { A[i]=(int*)malloc(N*sizeof(int)); } int s=0; int temp=

【CUDA并行编程之四】矩阵相乘

前面介绍了基本的Cuda编程的相关知识,那么这一篇在此基础之上来看看GPU在处理数据计算上的高效能,我们拿矩阵相乘来作为例子. 1.CPU上执行矩阵相乘以及性能. 在CPU上进行矩阵相乘运算的代码: mat_mul.cc: <span style="font-family:Microsoft YaHei;font-size:18px;">//a[i]*b[i] + c[i] = d[i] #include<iostream> #include<vector

C++面向对象编程解决三阶矩阵相加减

/*此处用面向对象编程*/ #include<iostream> #include<string.h> using namespace std; class Matrices { private: int mat[3][3]; public: Matrices(); void input() { for(int i=0; i<3; i++) { for(int j=0; j<3; j++) { cin>>mat[i][j]; } } } friend Mat

ACM编程题之矩阵翻转

题目: 晓萌最近在做一个翻转图片的应用,你可能也知道,图片其实是由一个个的点组成的. 于是,晓萌想先做一个可以翻转矩阵的程序,来解决他问题的核心部分. 输入第一行包括由空格分开的整数M.N.T(0<M<200,0<N<200,T=0或1), 其中M和N分别表示待处理矩阵的行数与列数,T为0时表示左右翻转,为1时表示上下翻转. 之后的M行,每行包括由空格分隔的N个整数,依次为输入矩阵的每一行的数据. 输出包括M行N列,每个数字之间用一个空格分隔,表示的是按照要求翻转后的矩阵. 样例输

Java-基础编程(螺旋矩阵&amp;乘法表)

package cn.rick.study; import java.io.BufferedReader;import java.io.InputStreamReader;import java.util.Scanner; /** * * @author Rick-bao date 2014-8-29 * */public class SomeBasicCode { public static void main(String[] args) { MultiplicationTable();//

趣味编程之九宫矩阵

题目描述: 将1-9这九个数字排成三行三列,使其行列.对角线上三数之和均相同,试编程求所有的可能: #include <iostream> using namespace std; int a[3][3], b[3][3]; int main() { int i, tx, ty; int x = 0, y = 1; a[0][1] = 1; //将1放在第0行第1列 for (i = 2; i <= 9; i++) { tx = (x + 2) % 3; ty = (y + 1) % 3

GEEK编程练习— —四数求和

题目 输入一个特定整数s和一组整数,要求从这组整数中找到四个数a,b,c,d,使a+b+c+d=s.按照升序排列,输出所有满足条件的a,b,c,d.具体格式如下: 输入 0 1 0 -1 0 -2 2 输出 -2 -1 1 2 -2 0 0 2 -1 0 0 1 分析 先排序,可以用hashmap缓存两个数的和,然后左右夹逼,时间复杂度O(n^2),空间复杂度O(n^2) 代码 #include <iostream> #include <vector> #include <u

GEEK编程练习— —雨水存储问题

题目 给定n个非负整数,分别代表围栏的高度,计算给定的这组数字代表的围栏能够容纳多少水,如图所示. 输入 0 1 0 2 1 0 1 3 2 1 2 1 输出 6 分析 对于每个柱子,找到其左右两边最高的柱子,该柱子能容纳的面积是min(max_left, max_right) - height.所以可以先扫描一遍,找到最高的柱子,将数组分为两半,然后分别进行处理. 代码 #include <iostream> #include <vector> using namespace s

GEEK编程练习— —最长相同的子串

题目 输入一行字符串,找出其中出现的相同且长度最长的字符串,输出它及首字符的位置. 输入 yyabcdabjcabceg 输出 abc 3 解析 首先声明一下,假如字符串为aaaaaa,答案应该为aaaaa.两个个等长的子串可以有部分字符重叠. 以abcab为例子分析如下: 首先寻找长度为4的子串,只能是abca和bcab,再查看这两个子串是否有其他相同的子串.有的话直接输出结果并退出程序. 然后寻找长度为3的子串,只能abc,bca,cab.这3个子串都没有其他相同的子串. 最后寻找长度为2的