編程雜談:蛇形方陣(斜對角型)

最近我看了一下大一新生程序設計階段考覈的狀況,情況很糟糕。本來我們學校的實力就不行,目前還是後繼無人,

我校對於競賽的支持也很少,要想把競賽做大做強,沒有好的生源,沒有好的導師,沒有好的培訓制度,

幾乎是癡人說夢。

下面就給出一個與在考覈中的某道題相似的問題,希望可以啓發學弟學妹的思路,也相當與給我來一個思維體操。</p>

問題描述

輸出一個階數爲n,元素爲1 到 n^2的斜對角型蛇形矩陣:

在這個矩陣中,
數字的遞增排列方向沿着方陣的副對角線方向迂迴排列,
即沿副對角線方向由上到小,再由下到上,從小到大依次
排列數字1—n^2.
比如:      
n = 3時

矩陣爲  

1 3 4

 2 5 8

6 7 9

(斜着看,先從斜上往斜下,再從斜下往斜上,是不是看到了1,2,3,...,9)

n = 5時

矩陣爲  

1    3   4   10  11

2    5   9   12  19
6    8   13  18  20

7    14  17  21  24

15  16  22  23  25

這是第一種實現方法:

/*******************************************************************************
實現語言:C++
解題思路:
用數組元素a[i][j](0 <= i, j < n)存放蛇形方陣
找出a[i][j]與i,j之間的函數關係,找函數關係
雖然比較麻煩,但是一旦找到,編程實現會非常簡
單。
函數關係如下:
n爲蛇形方陣的階數,a[i][j](0 <= i, j < n)爲方陣中第(i+1)行,第(j+1)列的元素
令m = i + j;
t(m) = m(m+1)/2,                      m < n
     = ((3n-m)(m-n+1)+n(n-1)) / 2,    n <= m <= 2(n-1);
    (t(m)爲對角線m=i+j中的最小元素)
a[i][j] = t(m) + i + 1,       (m < n) and (m % 2 == 0)
		= t(m) + j + 1,		  (m < n) and (m % 2 != 0)
		= t(m) + i - m + n,   (m >= n) and (m % 2 == 0)
		= t(m) + n - i,		  (m >= n) and (m % 2 != 0)
		
 由於給定i,j就可以確定a[i][j],不用數組存放方陣,直接輸出結果也是可以的
*****************************************************************************/
#include <iostream>
#include <cstdio>
using namespace std;

const int MAX_N = 10;

int main(void)
{
    int n;
    int a[MAX_N][MAX_N];

    while (cin >> n) {
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                int t, m = i + j;
                if (m < n) {
                    t = m * (m + 1) / 2;
                    if (m % 2 == 0)
                        a[i][j] = 1 + t + i;
                    else
                        a[i][j] = 1 + t + j;
                } else {
                    t = ((3*n-m)*(m-n+1) + n*(n-1)) / 2;
                    if (m % 2 == 0)
                        a[i][j] = t + i - (m - n);
                    else
                        a[i][j] = t + n - i;
                }
            }
        }

        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                printf("%5d", a[i][j]);
            }
            printf("\n");
        }
    }

    return 0;
}

下面給出第二種實現方法——模擬法,這種方法比較容易理解,要找的規律也很簡單,而不需要尋找複雜函數關係

但是必須用二維數組存放,沒有辦法給出i,j,就得到a[i][j].

/****************************************
實現語言:C++
解題思路:
(模擬法)
用二維數組a[i][j](0 <= i, j < n)存放蛇形方陣
可以發現,i+j相同的元素a[i][j]在同一個對角線
上,把這個規律作爲突破口,模擬手工排列蛇形
方陣的過程即可。由於思維過程較爲零散,具體思路
詳見代碼註釋。
*****************************************/
#include <iostream>
#include <cstdio>
using namespace std;


const int MAX_N = 10;


int main()
{
	int n, num;
	int a[MAX_N][MAX_N];
	int i, j;


	while (cin >> n) {
		//a[0][0] 元素爲1
        i = j = 0;
        a[i][j] = num = 1;
        //對角線的編號m = i + j
		for (int m = 1; m <= 2*n - 2; m++) {
			//m爲偶數,對角線上的數字遞增方向爲從上到下
			//否則,數字遞增方向爲從下到上
			if (m % 2 == 0) {
                if (j == n - 1) i++; else j++;   //調整座標(i, j)並填數字
                a[i][j] = ++num;


				while (j != 0 && i != n - 1) {   //在對角線上填寫數字,直到對角線末端
					i++; j = m - i;
					a[i][j] = ++num;
				}
			} else {                             //原理同上一代碼塊
                if (i == n - 1) j++; else i++;
				a[i][j] = ++num;


				while (i != 0 && j != n - 1) {
					i--; j = m - i;
					a[i][j] = ++num;
				}
			}
		}


		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				printf("%5d", a[i][j]);
			}
			printf("\n");
		}
	}


	return 0;
}
總之,要成爲編程高手,一定要持之以恆地不斷練習,而且是高質量的練習。

所以,學弟學妹們要加油啊!我已經沒什麼指望了,但你們還有時間,有精力,我校競賽的輝煌也許會出現在你們身上!!!

發佈了58 篇原創文章 · 獲贊 31 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章