Заполнить двумерный массив зигзагом по диагонали

Уровень сложности:

Требуется написать программу, которая заполняет массив размерности nxn по заданному правилу:

/*    1  3  4 10 11
      2  5  9 12 19
      6  8 13 18 20
      7 14 17 21 24
     15 16 22 23 25  */

То есть, заполнение массива должно быть по диагонали, сверху-вниз, слева-направо. Причем заполнение еще и зигзагообразное.

Смотрим результат работы программы:

По условию программы, массив — квадратная матрица, то есть имеет одинаковое количество строк и столбцов. Возможно это упростит задачу. Дам подсказку — рассмотрите массив как область в квадратной системе координат. То есть, для перемещения по элементам матрицы, мы условно будем пользоваться x и y координаты. х-координата — переменная, которая будет отвечать за перемещение по горизонтали (по столбцам), y-координата — отвечает за перемещение по вертикали (по строкам).

Мой способ решения состоит из двух этапов:

  • заполнение первой половины массива;
  • заполнение второй половины;

Например,

/*  заполнение первой половины массива (строки 16 - 44)
      1  3  4 10 11
      2  5  9 12  0
      6  8 13  0  0
      7 14  0  0  0
     15  0  0  0  0  */

ну и конечно же, заполнение остальной части массива (строки 48 — 76):

/*    0  0  0  0  0
      0  0  0  0 19
      0  0  0 18 20
      0  0 17 21 24
      0 16 22 23 25  */

Каждая часть массива заполняется отдельным циклом for, в котором перебор идет по диагоналям. Заметьте, что каждый новый столбец — это начало новой диагонали. Поэтому циклы for будут перебирать столбцы, предполагая, что это диагонали. То есть, каждая пройденная итерация цикла for — это заполненная диагональ.

Исходный код этой программы был бы в два раза меньше, но дело в том, что нужно организовать зигзагообразное заполнение. И поэтому, Для каждой заполняемой половины массива, нужно рассмотреть два случая:

  • заполнение диагонали снизу-вверх (для первой части — строки: 33 -42, второй части массива — строки: 65 — 74)
  • заполнение диагонали сверху-вниз (для первой части — строки: 20 -29, второй части массива — строки: 52 — 62)

И чтобы два способа заполнения диагоналей чередовались, мы делаем проверку в строке 18, для заполнения первой половины массива и в строке 50, для заполнения второй половины массива.

Непосредственно в циклах while выполняется заполнение диагоналей. В коде оставил много комментариев, надеюсь объяснил понятно.

#include <iostream>
#include <iomanip>
using namespace std;

int main()
{
    const int colum = 10; // количество столбцов массива
    const int row   = 10; // количество строк массива
    int array[100][100];

    int x, y,  // Координаты текущего элемента массива
        value = 1; // значение, которым заполняется массив

    // зполнение первой половины массива по диагонали, зигзагом, начиная
    // слева и сверху, заканчивая  побочной диагональю
    for (int diag = 0; diag < colum; diag++) // выполняем проход по диагоналям
    {
        if (diag % 2 == 0) // по четным диагоналям
        {
            x = 0; // х-координата первого лемента массива на диагонали - diag
            y = diag; // у-координата элемента массива на диагонали - diag

            while (y >= 0) // пока y-координата находится в верхней части диагонали
            {
                array[x][y] = value; // записать значение в массив
                value++;
                x++;     // по горизонтали, смещаемся влево
                y--;    // по вертикали, смещаемся вниз
            }
        }
        else // по нечетным диагоналям
        {
            x = diag; // х-координата элемента массива на диагонали - diag
            y = 0; // у-координата первого элемента массива на диагонали - diag

            while (x >= 0) // пока x-координата находится в левой части диагонали
            {
                array[x][y] = value; // записать значение в массив
                value++;
                x -= 1;  // по горизонтали, смещаемся вправо
                y +=  1; // по вертикали, смещаемся вверх
            }
        }
    } // конец for

    // заполнение второй половины массива по диагонали, зигзагом, начиная
    // слева и сверху, заканчивая  последним элементом массива
    for (int diag = 1; diag < colum; diag++)
    {
        if (diag % 2 == 0) // по четным диагоналям
        {
            x = 9; // х-координата первого элемента массива на диагонали - diag
            y = diag;  // у-координата элемента массива на диагонали - diag

            while (y <= 9) // Пока не кончилась диагональ
            {
                array[x][y] = value;
                value++;
                x--; // по горизонтали, смещаемся влево
                y++; // по вертикали, смещаемся вниз
            }
        }
        else // по не четным диагоналям
        {
            x = diag; // х-координата первого элемента к-ой диагонали
            y = 9;  // у-координата первого элемента к-ой диагонали

            while (x <= 9) // Пока не кончилась диагональ
            {
                array[x][y] = value;
                value++;
                x++; // по горизонтали, смещаемся вправо
                y--; // по вертикали, смещаемся вверх
            }
        } // конец if-else
    } // конец цикла for (заполнение второй половины массива)

    // вывод масиива на экран
    for (int ix = 0; ix < row; ix++)
    {
        for (int jx = 0; jx < colum; jx++)
            cout << setw(4) << array[ix][jx] << " ";
        cout << endl;
    }

    return 0;
}

Скорее всего мой код можно уменьшить, приблизительно в 2 раза, но у меня с ходу не получилось это сделать. Поэтому оставил все так. Если у вас получится уменьшить исходный код или найти другое решение, поделитесь с читателями нашего сайта. Ах да, я забыл реализовать в данной программе ввод размера массива, но я думаю это у вас получится и без меня. Пример работы программы:

CppStudio.com
   1    3    4   10   11   21   22   36   37   55 
   2    5    9   12   20   23   35   38   54   56 
   6    8   13   19   24   34   39   53   57   72 
   7   14   18   25   33   40   52   58   71   73 
  15   17   26   32   41   51   59   70   74   85 
  16   27   31   42   50   60   69   75   84   86 
  28   30   43   49   61   68   76   83   87   94 
  29   44   48   62   67   77   82   88   93   95 
  45   47   63   66   78   81   89   92   96   99 
  46   64   65   79   80   90   91   97   98  100
Следующие статьи помогут вам в решении данной задачи:
Автор: Marienko L.
Дата: 14.11.2012
Поделиться:

Комментарии

  1. vlad bolltrukanis

    int main()
    {
    int n; //razmer
    int c = 1; //chetchik cifr
    int s = 0; //schetchik polosi
    std::cout << «Size of matrix: «;
    std::cin >> n;
    int** mas = new int*[n];
    for (int i = 0; i < n; i++)
    {
    mas[i] = new int[n];
    };
    for (s; s < 2 * n; s++)
    {
    if (s % 2 == 1 || s == 1)
    {
    for (int i = 0; i < n; i++)
    {
    for (int j = 0; j < n; j++)
    {
    if (i + j == s)
    {
    mas[i][j] = c;
    c++;
    };
    };
    };
    }
    else
    {
    for (int j = 0; j< n; j++)
    {
    for (int i = 0; i < n; i++)
    {
    if (i + j == s)
    {
    mas[i][j] = c;
    c++;
    };
    };
    };
    };
    };
    for (int i = 0; i < n; i++)
    {
    for (int j = 0; j < n; j++)
    {
    std::cout << mas[i][j] << «\t»;
    };
    std::cout << std::endl;
    };
    for (int i = 0; i < n; i++)
    {
    delete[] mas[i];
    };
    delete[] mas;
    system(«pause»);
    return 0;
    }

  2. Eduard_P

    Eduard_P

    Вот мой код. Пришлось делать через метки, так как надо было входить и выходить

    из циклов в разных местах при четной и нечетной матрице. Матрица задается пользователем.

    #include <cstdlib>
    #include <iostream>
    #include <iomanip>
    
    using namespace std;
    
    /*
     * 
     */
    int main(int argc, char** argv) { 
        int n, i=0, j=0, k=1; 
        bool flag=0;
        cout << "Введите размерность квадратной матрицы: ";
        cin >> n;
        int matrix [n][n];
            
         matrix[i][j] = k;
    labale_1: //Цикл заполнения снизу вверх слева направо 1 половина
            if ((j==0)&(flag==0)) {i++; flag=1;}
            else { j++; i--;}
             k++;
             matrix[i][j] = k; 
        if (i>0) goto labale_1;    
        if (j==(n-1)) goto labale_4;//Выход из цикла 1 половины при четной матрице
       
    labale_2: //Цикл заполнения сверху вниз справа на лево 1 половина  
            if ((i==0)&(flag==1)) {j++; flag=0;}
            else {j--; i++;}
            k++;
            matrix[i][j] = k;    
        if (j>0) goto labale_2;  
        if (i==(n-1)) goto labale_3;//Выход из цикла 1 половины при нечетной матрице
        goto labale_1;//Цикл заполнения 1 половина
    
    labale_3://Цикл заполнения снизу вверх слева направо 2 половина
            if (i==(n-1)&flag==0) {j++; flag=1;}
            else {j++; i--;}
            k++;
            matrix[i][j] = k; 
        if (k==(n*n)) goto labale_5;//Выход - конец заполнения
        if (j<(n-1))  goto  labale_3; 
        
    labale_4://Цикл заполнения сверху вниз справа на лево 2 половина  
            if (j==(n-1)&flag==1) {i++; flag=0;}
            else {j--; i++;}
             k++;
             matrix[i][j] = k;  
        if (k==(n*n)) goto labale_5; //Выход - конец заполнения
        if (i<(n-1))  goto  labale_4;
        if (i==(n-1))  goto  labale_3;//Цикл заполнения 2 половина
    
    labale_5:          
    for (i=0; i<n; i++){
        for (j=0; j<n; j++){
            cout << setw(4) << matrix[i][j] << " ";
        }
        cout << "\n";
    }
        
        return 0;
    }
    
    
  3. mikemike

    Вот так вышло для квадратной матрицы:

    #include <iostream>
    #include <iomanip>
    using namespace std;
    void vivod_mass(int **ar, int size) {
    for (int i = 0; i < size; i++) {
    for (int j = 0; j < size; j++) {
    cout << setw(4) << ar[i][j];
    }cout << endl;
    }
    }
    int main() {
    int n, k, z, l;
    cout << «Vvdeite razmernost massiva: «;
    cin >> n;
    int **array;
    array = new int *[n];
    for (int i = 0; i < n; i++)
    array[i] = new int[n];
    k = 1;
    z = 0;
    l = 1;
    while (k <= pow(n, 2)) {
    for (int i = 0; i < n; i++) {
    for (int j = 0; j < n; j++) {
    if ((i + j) == z){
    if (l == 1) {
    array[i][j] = k;
    k++;
    break;
    }
    else {
    array[j][i] = k;
    k++;
    break;
    }
    }
    }
    }
    z++; l = -l;
    }
    vivod_mass(array, n);
    system(«pause»);
    return 0;
    }

  4. Shini_chi

    #include <iostream>
    #include <iomanip>
    
    using namespace std;
    
    int main ()
    {
        setlocale (LC_ALL, "rus");
        int number = 0, value = 1, xy = 0, yx = 0;
        cout << "Размеры массива = "; cin >> number;
        int array[number][number];
        //Заполнение левой части массива до побочной диагонали
        for (int x = 0; x < number; x++)
            if (x % 2 == 0)
            {
                yx = x;
                xy = 0;
                while (yx >= 0)
                {
                array[xy][yx] = value;
                value++;
                xy++;
                yx--;
                }
            }
            else
            {
                yx = 0;
                xy = x;
                while (xy >= 0)
                {
                    array[xy][yx] = value;
                    value++;
                    yx++;
                    xy--;
                }
            }
    if (number % 2 == 1) ///Если number нечетное
    {
        //Заполнение правой части массива
        for (int y = 1; y < number; y++)
        {
            if (y % 2 == 1)
            {
                yx = y;
                xy = number-1;
                while (xy >= y)
                {
                    array[xy][yx] = value;
                    value++;
                    xy--;
                    yx++;
                }
            }
            else
            {
                xy = y;
                yx = number-1;
                while (yx >= y)
                {
                    array[xy][yx] = value;
                    value++;
                    xy++;
                    yx--;
                }
            }
        }
    }
    
    else ///При четном number
    {
            //Заполнение правой части массива
        for (int x = 1; x < number; x++)
        {
            if (x % 2 == 1)
            {
                yx = number-1;
                xy = x;
                while (yx >= x)
                {
                    array[xy][yx] = value;
                    value++;
                    xy++;
                    yx--;
                }
            }
            else
            {
                yx = x;
                xy = number-1;
                while (xy >= x)
                {
                    array[xy][yx] = value;
                    value++;
                    xy--;
                    yx++;
                }
            }
        }
    }
        //Вывод на экран
        for (int count_row = 0; count_row < number; count_row++)
        {
            for (int count_column = 0; count_column < number; count_column++)
                cout << setw(3) << array[count_row][count_column];
            cout << endl;
        }
    
        //Удаление массива
        for (int count = 0; count < number; count++)
            delete [] array[count];
    
    return 0;
    }
  5. Алексей Бондаренко

     

    // Публикую свое решение
    
    #include <iostream>
    #include <iomanip>
    using namespace std;
    
    class Array {
    	public:
    		Array();
    		void Out();
    	private:
    		static const int n = 10; 
    		int A[n][n];
    };
    
    Array::Array()
    {
    	int Number = 0;
    	const int maxNumber = n * n;
    
    	for (int i = 0; i < n; i++) {
    		int i2 = i;
    		if (i % 2)
    			for (int j = 0 ; j <= i; j++, i2--) {
    				A[i2][j] = ++Number;
    				A[n - 1 - i2][n - 1 - j] = (maxNumber - Number + 1);
    			}
    		
    		else
    			for (int j = 0 ; j <= i; j++, i2--) {
    				A[j][i2] = ++Number;
    				A[n - 1 - j][n - 1 - i2] = (maxNumber - Number + 1);
    			}
    	}
    }
    
    void Array::Out()
    {
    	for (int i = 0; i < n; i++) {
    		for (int j = 0; j < n; j++)
    			cout << setw(5) << A[i][j];
    		cout << endl;
    	}
    }
    
    int main()
    {
    	Array A;
    	A.Out();
    	return 0;
    }
  6. colt

    Решение с комментариями для произвольного массива (даже в котором количество строк, не равно количеству столбцов):

    #include "stdafx.h"
    #include "iostream"
    #include "windows.h"
    
    using namespace std;
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        SetConsoleCP(1251);
        SetConsoleOutputCP(1251);
    	
    
    
        while(true)
        { 
    		system("CLS");
    		short rows, columns;
    		cout<<"Введите размер матрицы.\nКоличество строк: ";
    		cin>>rows;
    		cout<<"Количество столбцов: ";
    		cin>>columns;
    		system("CLS");
    
    		short **Matrix=new short*[rows];	//содаём динамический массив
    		for (int i=0;i<rows;i++)
    		{
    			Matrix[i]=new short[columns];
    		}
    
    		short i=0,j=0; 
    		short size=rows*columns;			//кол-во элементов динамического массива
    		bool downleft=true;					//если true, то змейка движется вниз и влево, если false то вверх и вправо
    		bool changedirection=false;			//флаг необходимости смены направления
    
    		for (int counter=1;counter<=size;counter++)
    		{
    			Matrix[i][j]=counter;			//записываем текущий счёт в массив змейку
    
    			if (downleft)					//формируем следующий индекс массива в случае движения вниз и влево
    			{
    				i++;						//движение вниз
    				j--;						//движение влево
    				if (i==rows)				//если вышли за предел массива вниз
    					{
    						i--;				//тогда меняем
    						j+=2;				//направление текущего шага
    						changedirection=true;		//и сообщаем о необходимости смены направления
    					}
    				else
    					{ 
    						if (j<0)			//если вышли за предел массива влево
    							{
    								j++;		//тогда меняем направление текущего шага
    								changedirection=true;	//и сообщаем о необходимости смены направления
    							}
    					}
    			}		
    			if (!downleft) //формируем следующий индекс массива в случае движения вверх и вправо
    			{
    				i--;						//движение вверх
    				j++;						//движение вправо			
    				if (j==columns)				//если вышли за предел массива вправо
    					{
    						j--;				//тогда меняем
    						i+=2;				//направление текущего шага
    						changedirection=true;		//и сообщаем о необходимости смены направления
    					}
    				else 
    					{ 
    						if (i<0)			//если вышли за предел массива вверх
    							{
    								i++;		//тогда меняем направление текущего шага
    								changedirection=true;	//и сообщаем о необходимости смены направления
    							}
    					}
    			}			
    			if (changedirection) downleft=!downleft;	//меняем направление
    			changedirection=false;	//обнуляем флаг необходимости смены направления
    		}	
    		
    		for (int i=0;i<rows;i++)	//выводим получившийся массив с заполнением в виде змейки
    		{
    			for (int j=0;j<columns;j++)
    			{
    				cout<<Matrix[i][j]<<"\t";
    			}
    			cout<<endl;
    		}
    		cout<<endl;
    
    		for (int i=0;i<rows;i++)	//удаляем динамический массив
    		{
    			delete [] Matrix[i];
    		}
    		system("PAUSE");
        }
        return 0;
    }

Оставить комментарий

Вы должны войти, чтобы оставить комментарий.