ccidnet????

出版日期:1997-10-27 总期号:681 本年期号:41

本期导读
综合要闻
网络通信
市场商情
国际文摘
技术专题
软件应用
′96程序员试题解答之我见

朱翠萍 汪浩

  1996年度中国计算机专业技术资格和水平考试中的程序员级下午试题的第三题是:

  [程序说明]

  本程序将自然数1,2...,n2按蛇形方式逐个顺序存入n阶矩阵。例如,当nΚ3和nΚ4时分别如图1和图2。

  7131416

  679681215

  25825911

  13413410

  图1图2

  从an0开始到a0n为止(nΚn-1)顺序填入自然数,交替地对每一斜列从左上向右下元素或从右下元素向左上元素存数。

  [程序]

  #includeΙstdio.hΛ

  #definesize10

  inta[size][size],k;

  main()

  {inti,j,n,n;

  for(nΚ3;nΙΚsize;n++)

  {kΚ1;makearray(nΚn-1);

  printf(″ιnnΚ%d:ιn″,n+1);

  for(iΚ0;iΙΚn;i++)

  {for(jΚ0;jΙΚn;j++)printf(″%4d″,a[i][j]);

  printf(″ιn″);}}}

  makeline(introw-start,intcol-start,introw-end)

  {/ 完成矩阵一条斜线的整数填写 /

  inti,j,signΚ----(1)----;

  for(iΚrow-start,jΚcol-start;-----(2)----ΛΚ0;i+Κsign,j+Κsign)

  a[i][j]Κk++;}

  makearray(intn)

  {/ 完成矩阵每条斜线的整数填写 /

  intd;

  for(dΚ1;dΙΚ----(3)----;d++)

  if(dΙΚn)

  if(d%2)makeline(----(4)----);elsemakeline(----(5)----);

  else

  if(d%2)makeline(----(6)----);elsemakeline(----(7)----);}

  此题公布的答案是:(1)row-endΛΚrow-start?1:-1;(2)(row-end-i) sign;(3)2 n+1;(4)n,d-1,n+1-d;(5)n+1-d,0,n;(6)2 n+1-d,n,0;(7)0,d-n-1,2 n+1-d。其主要解题思路是:在函数makearrary中由矩阵的当前斜列d是否大于n及d的奇偶性来决定调用函数makeline的方式;在函数makeline中由起始行与起始列的大小来决定变量sign为正1还是负1,由此决定在斜列中填数的方向以及行和列的变化;将形参row-end看成在斜列上填数的终止行的位置,由(row-end-i) sign的大小决定在每一斜列上填数的个数。具体分析与解答过程请参阅中国计算机专业技术资格和水平考试统编辅导教材之《试题分析与解答》第82、83页(由上海交通大学出版社出版)。

  这种解题思路虽然比较简单,但不容易理解与计算。仔细分析此矩阵,可以发现此题还有一种更为简单的解题思路,以下是笔者的分析过程:

  (1)显然,主函数的循环是控制顺序生成3x3、4x4、…、10x10的蛇形矩阵。函数makearrary应完成对矩阵每条斜线的整数填写,而每一矩阵具有(2 n+1)条斜列,所以d的取值范围是从1到(2 n+1)。因此(3)处应填入(2 n+1)。

  (2)通过对图1和图2这两个具体实例的分析,可以得到如表一的表格。

  由矩阵的特性可知,此表格同样适用于n阶矩阵。

  (3)通过上面的表格,可以发现d的奇偶性与在斜列上填数的个数的奇偶性一致,并由其奇偶性决定了在斜线上填数的方向。也就是当d为奇数时,每一斜列从右下元素向左上元素存数,行和列递减1;当d为偶数时,对每一斜列从左上向右下元素存数,行和列递增1。程序中指明了变量sign为行和列的每次增量,因此可将makeline函数中的形参row-end看着在某一斜列线上填数的个数,并由其奇偶性决定变量sign是为正1还是为负1。所以可在(1)处填上(row-end%2ΚΚ0?1:-1),在(2)处填上(--row-end)。

  (4)在函数makearrary中调用makeline时,应分别传递起始行(i)、起始列(j)及填数个数(row-end)等三个变量。所以,在(4)-(7)处可分别填上(n,d-1,d),(n-d+1,0,d),(2 n+1-d,n,2 n+2-d),(0,d-n-1,2 n+2-d)。

  经上机运行,验证了这种解题思路是可行的。因此,此题的另一解答就是:(1)row-end%2ΚΚ0?1:-1;(2)--row-end;(3)2 n+1;(4)n,d-1,d;(5)n-d+1,0,d;(6)2 n+1-d,n,2 n+2-d;(7)0,d-n-1,2 n+2-d。

  此解题思路可以归纳为:在函数makearrary中由矩阵的当前斜列d是否大于n来决定在每一斜列中填数的个数,并将此数值传递给形参row-end;在函数makeline中将row-end看成在斜列中填数的个数,由row-end来决定填数的次数;由row-end的奇偶性来决定变量sign为正1还是负1,并由sign来决定在斜列中填数的方向以及行和列的变化。

  可以看出,由于对形参row-end的含义的理解不同,得到了两种不同的解题思路。可以猜想,出题者可能原本是想让考生由参数row-end的英文含义推出解题思路的,但这也恰恰限制了考生的另一种较直观的解题思路。