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

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

ybt 2045: [example 5.13] snake filling number

## [title test site]

#### 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++