## [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; }