![]() ![]() |
|
计算机等级考试三级网络复习资料总录 | |
作者:佚名 文章来源:不详 点击数 更新时间:2007/11/12 10:45:32 文章录入:杜斌 责任编辑:杜斌 | |
|
|
设n=100,c=1,m=10. (1)将1到n个人的序号存入一维数组p中; (2)若第i个人报数后出圈,则将p[i]置于数组的倒数第i个位置上,而原来第i+1个至倒数第i个元素依次向前移动一个位置; (3)重复第(2)步直至圈中只剩下p[1]为止。 部分源程序已给出。 请勿改动主函数main()和输出数据函数writedat()的内容。 #include <stdio.h> #define n 100 #define s 1 #define m 10 int p[100],n,s,m; void writedat(void); void josegh(void) { } void main() { m=m; n=n; s=s; josegh(); writedat(); } void writedat(void) { int i; file *fp; fp=fopen('out.dat' ,' w' ); for(i=n-1;i>=0;i--){ printf(' %4d' ,p[i]); fprintf(fp,' %4d' ,p[i]); if(i % 10==0){ printf('/n' ); fprintf(fp, '/n' ); } } fclose(fp); } 解法: 这是南开题中的极品,其实个人认为这个题目是的要求很低,只是要你把题目中描述的算法用代码实现出来。 题目中已经给出了算法过程,我们下面就看看怎么用代码实现: (1)将1到n个人的序号存入一维数组p中; 这个我想大家应该都没有问题的了:很简单的一句循环赋值。 for(i=1;i<=n;i++)p[i-1]=i; (2)若第i个人报数后出圈,则将p[i]置于数组的倒数第i个位置上,而原来第i+1个至倒数第i个元素依次向前移动一个位置; (3)重复第(2)步直至圈中只剩下p[1]为止。 难点就在这后面两步,首先可以看出是要做一个循环,而且循环的条件是递减 马上可以先写出一个循环递减的框架 for(i=n;n>1;n--){} 接下来就是该怎么写循环体的内容了:我们可以发现,题目的算法过程2描述的很清楚,具体如下: s=(s+m-1)%i;首先,求出出圈人的位置,这里用一个求余是为了实现圈循环(也就是将队列头尾相连),这里i是圈中剩余的人数(除去出圈后的人)。 当然,我们稍微注意一下,那就是没有第0位的出圈人存在,所以这里如果s=0是不对的, 其实这种情况是出圈人是队尾的那一个人,所以这里加上一个判断: if(s==0)s=i; 好了,我们取到了出圈人的位置了,那我们就要: '则将p[i]置于数组的倒数第i个位置上,而原来第i+1个至倒数第i个元素依次向前移动一个位置' 实现这一句的算法过程的代码,可以看出也是一个循环: w=p[s-1]; 首先,把出圈人的号码暂时放起来(因为此时倒数第i个位置还有人占据,不能替换掉) 接着我们要把倒数第i个位置腾空出来, 而这个算法的实现就是“第i+1个至倒数第i个元素依次向前移动一个位置” 明白了这句话的意思后,马上可以写出下面的一个循环代码来实现 for(j=s;j<i;j++)p[j-1]=p[j];出圈人的位置让给他的下一位,依次类推,最后腾出倒数第i个位置给出圈人。 最后出圈人占据倒数第i个位置:p[i-1]=w;(注意这里第i个位置在数组中下标是i-1,因为数组下标是0开始的, 到这里为止,循环体也写完了,整合起来,就可以得到下面的完整函数代码了: void josegh(void) { int i,j,w; 定义一些用于暂时存放出圈人和循环变量。 for(i=1;i<=n;i++) 开始初始化循环赋值。 p[i-1]=i; for(i=n;i>=2;i--) 循环体开始 {s=(s+m-1)%i; 寻找出圈人 if(s==0) s=i; w=p[s-1]; 暂时安置出圈人 for(j=s;j<i;j++) 给出圈人腾位置 p[j-1]=p[j]; p[i-1]=w; 重新安置出圈人 } } |
|
![]() ![]() |