2012年3月10日 星期六

a417: 螺旋矩陣

內容 :
輸出一螺旋矩陣。

輸入說明 :
每行有一正整數T,代表有幾組測試資料
接下來有T行, 每行有N、M兩正整數
N為矩陣長寬,就是會有N*N矩陣
M為方向,M=1為順時鐘,M=2為逆時鐘
N範圍為1~100之間

輸出說明 :
把矩陣輸出,矩陣值之間寬度為5,就是[00000]寬度
C++可用setw(5)或C的%5d輸出

範例輸入 :
2
3 1
2 2

範例輸出 :
1 2 3
8 9 4
7 6 5

1 4
2 3

程式碼 :
#include<stdio.h>
#include<stdlib.h>

int main()
{
    int i,j,t,n,m,x,y,loop,times,mode,count;
    int pathx[4] = {1,0,-1,0};
    int pathy[4] = {0,-1,0,1};
    
    while(scanf("%d",&t)==1)
    {        
        while(t--)
        {
            scanf("%d%d",&n,&m);
            
            int **arr = (int**)malloc(sizeof(int *) * n);
            for(i=0; i<n; i++)
                arr[i] = (int*)malloc(sizeof(int) * n);
            
            count = 0;
            loop = (n-1) * 2;
            times = n;
            mode = 0;
            if(m == 1)
            {
                x = 0;
                y = -1;
                for(i=0; i<n; i++)
                {
                    y = y + 1;
                    arr[x][y] = ++count;
                }
            }
            else
            {
                x = -1;
                y = 0;
                for(i=0; i<n; i++)
                {
                    x = x + 1;
                    arr[x][y] = ++count;
                }
            }
            for(i=0; i<loop; i++)
            {
                if(i%2 == 0)
                    times--;
                for(j=0; j<times; j++)
                {
                    if(m == 1)
                    {
                        x = x + pathx[mode];
                        y = y + pathy[mode];
                    }
                    else
                    {
                        x = x + pathy[mode];
                        y = y + pathx[mode];
                    }
                    arr[x][y] = ++count;
                }
                mode = (mode+1) % 4;
            }            
            
            for(i=0; i<n; i++)
            {
                for(j=0; j<n; j++)
                    printf("%5d",arr[i][j]);
                printf("\n");
            }
            if(t != 0)
                printf("\n");
        }
    }        
    return 0;
}


http://zerojudge.tw/ShowProblem?problemid=a417

4 則留言:

  1. 能簡單的解說一下嗎??
    從20~62行

    回覆刪除
  2. Line20. count是我們要的數字,也就從1數到n。

    Line21. loop是要重複幾次,以N=3,M=1為例,我們可以看出輸出的規律,123->45->67->8->9,其中"->"代表換方向,除了123以外,我總共要做另外四次的輸出,而且這四次的輸出有規律,每經過兩次他印出的數量就會少一個,所以為了得到loop,我們透過公式(n-1) * 2求得需要迴圈的次數。

    Line22. times就是每次loop要印出幾個數,以印出45為例,有兩個數要印出來,所以times=3(<-因為是小於,所以加一)
    Line23. mode是控制存入此數的位置
    Line24-42. 處理一開始沒有規律的部分,以上面的例子也就是"123"
    Line44-63. 處理有規律的部分,以上面的例子也就是"45->67->8->9"

    回覆刪除
  3. 我想到的寫法
    #include
    int series(int initial, int difference, int baseline, int height)
    {
    return initial + height * (difference + (((baseline << 1) - height - 1) << 2));
    }
    int main()
    {
    int T, N, M, i, j, *_i, *_j, p, q;
    while(scanf("%d",&T) == 1)
    while(T--)
    {
    scanf("%d %d", &N, &M);
    --N;
    if(--M)
    _i = &j, _j = &i;
    else
    _i = &i, _j = &j;
    for(*_i = 0; *_i <= N; ++*_i, printf("\n"))
    for(*_j = 0; *_j <= N; ++*_j)
    printf("%5d", series((3 * p + q - (p * q << 1)) * N + 1, ((-3 * p - q + (p * q << 1) + 4) << 1) + (N << 2 & 4), N >> 1, (1 - p - q) * i + (p - q) * j + q * N) + ((q << 1) - 1) * i - ((p << 1) - 1) * j + (p - q) * N,p = i > j, q = j > N - i);
    printf("\n");
    }
    return 0;
    }

    回覆刪除