Informatics Olympiad all in one 2045: [example 5.13] snake number

Posted by lunarul on Tue, 04 Jan 2022 01:26:18 +0100

[title link]

ybt 2045: [example 5.13] snake filling number

[title test site]

1. Two dimensional array

2. Direction array (may be used)

int dir[4][2] = {{1,0},{0,-1},{-1,0},{0,1}};
d is the current direction, 0: down, 1: left, 2: up, 3: right
dir[d] is the change of the abscissa and ordinate after moving in the d direction, that is, the next position to which the position (x,y) moves in the d direction is (x+dir[d][0], y+dir[d][1])

[problem solving ideas]

Method 1: move the focus position

Set a two-dimensional array, and the initial value of each position is 0. Set the focus position of attention (fx, fy), the initial value is 1, and the position (1, n). A variable is used to represent the moving direction of the current focus, and the initial value is down.
First assign the focus position to 1, move the focus once according to the current moving direction, then assign the new position to 2, and then repeat the moving and assignment operations. If you move out of the range of the two-dimensional array, or the position of the focus after moving has a value (not 0), change the moving direction. The moving direction changes circularly in the order of bottom, left, top and right.
The direction can be represented by an integer d, 0: lower 1: left 2: upper 3: right. If you want to change to the next direction, just run: d = (d + 1)% 4.
This method can be realized by judging the current direction, doing different operations, or using direction array

Method 2: assign value by circle

Traverse and assign values from outside to inside in circles.

  • The first cycle traversal process is: (1,n) down to (n,n), (n, n-1) left to (n, 1), (n-1, 1) up to (1,1), (1,2) right to (1, n-1)
  • The second cycle traversal process is: (2,n-1) down to (n-1,n-1), (n-1, n-2) left to (n-1, 2), (n-2, 2) up to (2,2), (2,3) right to (2, n-2)
    ...
  • According to the law, the ergodic process of cycle I is: (i, n-i+1) down to (n-i+1,n-i+1), (n-i+1, n-i) left to (n-i+1, i), (n-i,i) up to (i,i), (i,i+1) right to (i, n-i)
  • When n is 1, there is 1 turn, when n is 2, there are 2 turns, when n is 3, and when n is 4, there are 2 turns... In total ⌈ n 2 ⌉ \lceil \frac{n}{2} \rceil ⌈ 2n ⌉ circle

[solution code]

Solution 1: move the focus position

  • Use the judgment statement to judge the current moving direction
#include<bits/stdc++.h>
using namespace std;
int main()
{
    int a[25][25] = {}, n, fx, fy;//The initial values of each element of array a are 0, FX and FY are the focus positions 
    int dir = 0;//Indicates direction 0: down 1: left 2: up 3: right
    cin >> n;//2D array width 
    fx = 1, fy = n; //Starting focus position (1, n) 
    for(int i = 1; i <= n*n; ++i)//A total of n*n lattices 
    {//The position of the number i is fx, fy 
        a[fx][fy] = i;
        switch(dir)//Judge the moving direction
        {
            case 0://lower
                fx++;//Focus moves down 
                if(fx == n || a[fx+1][fy] != 0)//If you have reached line n, or the next location has a value 
                    dir = (dir + 1) % 4;//The moving direction changes to the next direction 
                break;
            case 1://Left
                fy--;
                if(fy == 1 || a[fx][fy-1] != 0)
                    dir = (dir + 1) % 4;
                break;
            case 2://upper
                fx--;
                if(fx == 1 || a[fx-1][fy] != 0)
                    dir = (dir + 1) % 4;
                break;
            case 3://right
                fy++;
                if(fy == n || a[fx][fy+1] != 0)
                    dir = (dir + 1) % 4;
                break;
        }
    }
    for(int i = 1; i <= n; ++i)//Output 2D array 
    {
        for(int j = 1; j <= n; ++j)
            cout << a[i][j] << ' ';
        cout << endl;
    }
    return 0;
}
  • Use direction array
#include<bits/stdc++.h>
using namespace std;
int dir[4][2] = {{1,0},{0,-1},{-1,0},{0,1}};//Direction array 
int main()
{
    int a[25][25] = {}, k = 1, n, fx, fy, d = 0, x, y;//fx, fy current focus position x,y next position d: direction 
    cin >> n;
    fx = 1, fy = n;
    while(k <= n*n)
    {
        a[fx][fy] = k++; // assignment 
        x = fx + dir[d][0], y = fy + dir[d][1]; //Next position 
        if(a[x][y] != 0 || x > n || x < 1 || y > n || y < 1)//If there is already a value in the new position or it is moved out of the range of the two-dimensional array
            d = (d + 1) % 4;//Change direction 
        fx += dir[d][0], fy += dir[d][1];//Update focus position 
    }
    for(int i = 1; i <= n; ++i)
    {
        for(int j = 1; j <= n; ++j)
            cout << a[i][j] << ' ';
        cout << endl;
    }
    return 0; 
}

Solution 2: assignment by cycle

#include <bits/stdc++.h>
using namespace std;
int main()
{
    int a[25][25], n, cnum, x, y, k = 1;
    cin >> n;
    cnum = ceil((double)n/2);//There are cnum cycles. When n is 1 and 2, it needs to traverse 1 cycle, and when n is 3 and 4, it needs to traverse 2 cycles... ceil: round up 
    for(int i = 1; i <= cnum; i++)//Circle i 
    {
        for(x = i, y = n-i+1; x <= n-i+1; x++)//Top right to bottom right 
            a[x][y] = k++; 
        for(x = n-i+1, y = n-i; y >= i; y--)//Bottom right to bottom left 
            a[x][y] = k++; 
        for(x = n-i, y = i; x >= i; x--)//Bottom left to top left 
            a[x][y] = k++; 
        for(x = i, y = i+1; y <= n-i; y++)//Top left to top right 
            a[x][y] = k++; 
    }
    for(int i = 1; i <= n; i++)//output 
    {
        for(int j = 1; j <= n; j++)
            cout << a[i][j] << ' ';
        cout << endl;
    }
    return 0;
}

Topics: C++