最近我看了一下大一新生程序設計階段考覈的狀況,情況很糟糕。本來我們學校的實力就不行,目前還是後繼無人,
我校對於競賽的支持也很少,要想把競賽做大做強,沒有好的生源,沒有好的導師,沒有好的培訓制度,
幾乎是癡人說夢。
下面就給出一個與在考覈中的某道題相似的問題,希望可以啓發學弟學妹的思路,也相當與給我來一個思維體操。</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 196 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;
}
總之,要成爲編程高手,一定要持之以恆地不斷練習,而且是高質量的練習。
所以,學弟學妹們要加油啊!我已經沒什麼指望了,但你們還有時間,有精力,我校競賽的輝煌也許會出現在你們身上!!!