#include using namespace std; int main() { // 1. 入力情報取得. int N; cin >> N; // 2. 数字の渦巻きを作る? // ex. // N = 4 の 場合. // 4 -> 3 -> 3 -> 2 -> 2 -> 1 -> 1 // したがって, 以下のような数列をイメージすることになる. // N -> N - 1 -> N - 1 -> N - 2 -> N - 2 -> ... -> 2 -> 2 -> 1 -> 1 vector v; int count = N; v.push_back(N - 1); // N だと上手く行かなかった. count--; while(count > 0) v.push_back(count), v.push_back(count), count--; // for(auto &p : v) cout << p << " " << endl; // 3. 二次元配列(r, c)成分は, 何番目? // dr, dc を使って, 右 -> 下 -> 左 -> 上 -> 右 -> ... を繰り返す方針で考える. int dr[4] = {0, 1, 0, -1}, dc[4] = {1, 0, -1, 0}; int ans[N][N]; int index = 1; ans[0][0] = index; // (前回)行, 列インデックス. int befR = 0, befC = 0; // 上下左右の向き判定フラグ. int flag = 0; for(auto &p : v){ // 3-1. (前回)行, 列インデックス. int curR = befR, curC = befC; // 3-2. 二次元配列更新. for(int i = 0; i < p; i++){ curR += dr[flag], curC += dc[flag]; ans[curR][curC] = ++index; // cout << "curR:" << curR << " curC:" << curC << " index:" << index << endl; // ex. // N = 3 の 場合. // curR:0 curC:1 index:2 // curR:0 curC:2 index:3 // curR:1 curC:2 index:4 // curR:2 curC:2 index:5 // curR:2 curC:1 index:6 // curR:2 curC:0 index:7 // curR:1 curC:0 index:8 // curR:1 curC:1 index:9 } // 3-3. flag更新. (++flag) %= 4; // cout << "flag=" << flag << endl; // 3-4. 前回分更新. befR = curR, befC = curC; } // 4. 出力. // for(int i = 0; i < N; i++) for(int j = 0; j < N; j++) cout << ans[i][j] << " "; // ex. // N = 3 の 場合. // -> 1 2 3 8 9 4 7 6 5 // string ans = ""; // cout << ans << endl; for(int i = 0; i < N; i++){ for(int j = 0; j < N; j++){ cout << setfill('0') << setw(3) << ans[i][j] << " "; } cout << endl; } return 0; }