1. 程式人生 > 實用技巧 >1050.螺旋矩陣-PAT乙級

1050.螺旋矩陣-PAT乙級

本題要求將給定的 N 個正整數按非遞增的順序,填入“螺旋矩陣”。所謂“螺旋矩陣”,是指從左上角第 1 個格子開始,按順時針螺旋方向填充。要求矩陣的規模為 m 行 n 列,滿足條件:m×n 等於 N;m≥n;且 m−n 取所有可能值中的最小值。

輸入格式:

輸入在第 1 行中給出一個正整數 N,第 2 行給出 N 個待填充的正整數。所有數字不超過 104,相鄰數字以空格分隔。

輸出格式:

輸出螺旋矩陣。每行 n 個數字,共 m 行。相鄰數字以 1 個空格分隔,行末不得有多餘空格。

輸入樣例:

12
37 76 20 98 76 42 53 95 60 81 58 93

輸出樣例:

98 95 93
42 37 81
53 20 76
58 60 76

分析:N=m x n其中m>=sqrt(N)>=n,所以讓m、n=sqrt(N),若此時m x n<N則m++,m x n>N則n--,若m x n=N則找到滿足條件的m、n。申請m x n陣列,將排序號的陣列元素按以下方式填入(狀態機思想):定義四種狀態(UP\DOWN\LEFT\RIGHT)檢測條件轉變狀態。題目中的矩陣是順時針填充,即遍歷方向是 起點 -> 向右填充 -> 向下填充 -> 向左填充 -> 向上填充 -> 向右填充...迴圈往復,全部填滿時結束。當我們完成每一個橫向或豎向填充過後,要填充的矩陣縮小,因此我們修改矩陣的四點座標(右上角為座標起點(0,0))四點座標分別為(min_i, min_j)、(min_i, max_j)、(max_i, max_j)、(max_i, min_j)然後進行下一方向填充。即可得到結果。

#include <iostream>
#include <vector>
#include <math.h>
#include <algorithm>
#define LEFT 0
#define RIGHT 1
#define UP 2
#define DOWN 3
using namespace std;

int main()
{
    int N, m, n;
    cin >> N;
    vector<int> v(N);
    for (int i = 0; i < N; i++)
        cin >> v[i];
    m = n = sqrt(N);
    while (m * n != N)
    {
        if (m * n > N)
            n--;
        else
            m++;
    }
    sort(v.begin(), v.end());
    vector<vector<int>> res(m, vector<int>(n));
    int state = RIGHT;
    int max_i = m - 1, max_j = n - 1, min_i = 0, min_j = 0, i = 0, j = 0;
    for (int k = N - 1; k >= 0; k--)
    {
        int temp = v[k];
        switch (state)
        {
        case LEFT:
            if (j == min_j)
            {
                state = UP;
                max_i--;
                res[i--][j] = temp;
            }
            else
                res[i][j--] = temp;
            break;
        case RIGHT:
            if (j == max_j)
            {
                state = DOWN;
                min_i++;
                res[i++][j] = temp;
            }
            else
                res[i][j++] = temp;
            break;
        case UP:
            if (i == min_i)
            {
                state = RIGHT;
                min_j++;
                res[i][j++] = temp;
            }
            else
                res[i--][j] = temp;
            break;
        case DOWN:
            if (i == max_i)
            {
                state = LEFT;
                max_j--;
                res[i][j--] = temp;
            }
            else
                res[i++][j] = temp;
            break;
        }
    }
    for (int i = 0; i < m; i++)
        for (int j = 0; j < n; j++)
            cout << res[i][j] << ((j == n - 1) ? "\n" : " ");
    return 0;
}