C++程序设计-第十一周循环结构程序设计上机实践项目

回到课程主页,链接:C++程序设计课程主页-2012级

  本次上机对应的教学内容:第3章   C++程序设计初步


【项目1:学会单步执行和调试程序】

  利用你上周编过的求1000以内所有偶数的和的程序,练习:(1)单步执行功能(掌握Step Over(F10)、Step Into(F11)、Step Out和Run to Cursor功能);(2)在程序中设置和取消断点,然后用Go命令(F5)执行,观察变量及程序流程的变化;(3)选择一个你以前做的程序,请你的同学在你的程序中作两处改动(改动者要想办法使坏才是,或者干脆请你的同学将他/她以前做过的程序改两处),使其语法正确,但可能会造成逻辑错误(如两数交换的程序中将a=b;和b=t;两条语句换一下顺序),你利用自己的思考和调试工具将程序改正过来。
  请将第(3)个要求写成博文进行记录。讲清楚过程和结果即可,文体不限,如果能像写出侦探小说中“破案”的味道就更好了。贺老师师的“代码侦探”专栏中的两篇文章供参考-http://blog.csdn.net/column/details/bugkiller.html
  提示:完成本题需要的技能见博文《VC++6.0调试工具使用初步》-地址:http://blog.csdn.net/sxhelijian/article/details/8129059


【项目2:穷举法解决组合问题】

  先阅读例题,领会穷举法(意为“穷尽式列举”,也称枚举)的思想,然后自行选题进行解决,掌握这种程序设计的一般方法。

  例题:小明有五本新书,要借给A,B,C三位小朋友,若每人每次只能借一本,则可以有多少种不同的借法?
  问题分析与算法设计:本问题实际上是一个排列问题,即求从5个中取3个进行排列的方法的总数。首先对五本书从1至5进行编号,然后使用穷举的方法。假设三个人分别借这五本书中的一本,当三个人所借的书的编号都不相同时,就是满足题意的一种借阅方法。
  下面是程序及其注释,要注意利用三重循环“穷举”
  程序:

#include <iostream> 
using namespace std;
int main()
{
	int a,b,c,count=0;
	cout<<"小明借书给三位小朋友书的方案有:"<<endl;
	for(a=1;a<=5;a++)	 //穷举a借5本书中的1本的全部情况
		for(b=1;b<=5;b++)	 //穷举b借5本书中的一本的全部情况
			for(c=1;c<=5;c++)	//穷举c借5本书中的1本的全部情况
				if(a!=b&&c!=a&&c!=b) //判断三个人借的书是否不同
				{
					++count;
					cout<<count<<": "<<a<<", "<<b<<", "<<c<<endl;//输出方案
				}
}

  任务:利用穷举的方法解决下面的问题(选做一道即算完成任务,其他可以抽时间自由安排,多做会使你更聪明。)

  (1)百钱百鸡问题:中国古代数学家张丘建在他的《算经》中提出了著名的“百钱买百鸡问题”:鸡翁一,值钱五,鸡母一,值钱三,鸡雏三,值钱一,百钱买百鸡,问翁、母、雏各几何?
  提示:设鸡翁、鸡母、鸡雏的个数分别为x,y,z,题意给定共100钱要买百鸡,若全买公鸡最多买20只,显然x的值在0~20之间;同理,y的取值范围在0~33之间,可得到下面的不定方程:
  5x+3y+z/3=100
  x+y+z=100
  所以此问题可归结为求这个不定方程的整数解。
  由程序设计实现不定方程的求解与手工计算不同。在分析确定方程中未知数变化范围的前提下,可通过对未知数可变范围的穷举,验证方程在什么情况下成立,从而得到相应的解。
  引申:这类求解不定方程的实现,各层循环的控制变量直接与方程未知数有关,且采用对未知数的取值范围上穷举和组合的方法来复盖可能得到的全部各组解。如果要采取技巧,往往是根据题意,更合理地设置循环控制条件来减少这种穷举和组合的次数,提高程序的执行效率,需要具体问题具体分析。


  (2)换分币:用一元人民币兑换成1分、2分和5分硬币,有多少种不同的兑换方法?
  提示:根据题意设i,j,k分别为兑换的1分、2分、5分硬币的枚数,则i,j,k的值应满足:i+j*2+k*5=100,根据取值范围构造循环解题即可。


  (3)年龄几何:张三、李四、王五、刘六的年龄成一等差数列,他们四人的年龄相加是26,相乘是880,求以他们的年龄为前4项的等差数列的前20项。
  提示:设数列的首项为a,则前4项之和为"4*n+6*a",前4 项之积为"n*(n+a)*(n+a+a)*(n+a+a+a)"。同时"1<=a<=4","1<=n<=6"。可采用穷举法求出此数列。


  (4)三色球问题:若一个口袋中放有12个球,其中有3个红的。3个白的和6个黒的,问从中任取8个共有多少种不同的颜色搭配?
  提示:设任取的红球个数为i,白球个数为j,则黒球个数为8-i-j,根据题意红球和白球个数的取值范围是0~3,在红球和白球个数确定的条件下,黒球个数取值应为8-i-j<=6。


  (5)委派任务:某侦察队接到一项紧急任务,要求在A、B、C、D、E、F六个队员中尽可能多地挑若干人,但有以下限制条件:

  •  A和B两人中至少去一人;
  • A和D不能一起去;
  • A、E和F三人中要派两人去;
  • B和C都去或都不去;
  • C和D两人中去一个;
  • 若D不去,则E也不去。
  问应当让哪几个人去?
  提示:用a、b、c、d、e、f六个变量表示六个人是否去执行任务的状态,变量的值为1,则表示该人去;变量的值为0,则表示该人不参加执行任务,根据题意可写出表达式:
  • a+b>1   //A和B两人中至少去一人;
  • a+d!=2     //A和D不能一起去;
  • a+e+f==2   // A、E、F三人中要派两人去;
  • b+c==0或b+c==2   // B和C都去或都不去;
  • c+d==1     //C和D两人中去一个;
  • d+e==0或d==1     //若D不去,则E也不去(都不去;或D去E随便)。
  上述各表达式之间的关系为“与”关系。穷举每个人去或不去的各种可能情况,代入上述表达式中进行推理运算,使上述表达式均为“真”的情况就是正确的结果。


  (6)警察局抓住了A、B、C、D四名盗窃嫌疑犯,其中只有一人是小偷。在审问时,A说:“我不是小偷”;B说:“C是小偷”;C说:“小偷肯定是D”;D说:“C在冤枉好人”。现在已经知道这四人中有三人说的是真话,一人说的是假话。请问到底谁是小偷?
  提示:设4个变量a,b,c,d,为0时表示不是小偷,为1时表示是小偷,用四重循环穷举a,b,c,d可能的取值的组合,对每一种组合判断其是否符合题目中给出的约束。最后结论:C是小偷。


  (7)在下面的加法算式中,不同的符号代表不同的数字,相同的符号代表相同的数字。请设计程序求出"都、要、学、C"4个符号分别代表的数字。

          学  C
      要  学  C
+ 都  要  学  C
________________
  2   0   0   8

  提示:让计算机解奥数题。穷举"都、要、学、C"4个符号分别代表的数字(从0到9),然后进行组合,如果组合起来符合规则(不同的符号代表不同的数字,相同的符号代表相同的数字,且使等式成立),则为正解。


  (8)下列乘法算式中:每个汉字代表1个数字(1~9)。相同的汉字代表相同的数字,不同的汉字代表不同的数字。试编程确定使得整个算式成立的数字组合,如有多种情况,请给出所有可能的答案。

       赛软件
    ×   比赛
____________
   = 软件比拼


  (9)有等式[※×(※3+※)]^2=8※※9,其中※处为1个数字,滴上了墨水无法辨认。请编程找出※表示哪个数字。(^指乘方)
  拓展:有等式[※×(※3○※)]^2=8※※9,其中※处为1个数字,○处为+、-、×、÷四个运算符之一,现滴上了墨水无法辨认。请编程找出※表示哪个数字,○表示哪个运算符。

【项目3- 有趣的数字】

  先阅读例题,体会处理数字的一般方法,然后自行选题进行解决,掌握这种类型程序设计的一般方法。
  例题:求满足条件n=a!+b!+c!的所有三位数n并输出,其中a,b,c分别为n的百、十、个位数。
  分析:就是将每个三位数逐个处理(用循环),对于每个数(循环体内要干的事),分离出个十百位,计算其阶乘和,然后和当前的三位数比较即可得出结论。
  参考程序如下:(此处用了while循环,实际上在此处for循环更合适,计数型的嘛)

#include<iostream>  
using namespace std;  
int main()  
{  
    int n,a,b,c,sum=0;  
	int i,f;
    n=100;  
    while(n<1000)  
    {  
		c=n%10;  //个位数,
		b=(n/10)%10;  //十位数
		a=n/100;  //百位数
		for(f=1,i=1;i<=a;++i)  
			f=f*i; //求 a!
		sum += f; 
		for(f=1,i=1;i<=b;++i)  
			f=f*i; //求 b!
		sum += f; 
		for(f=1,i=1;i<=c;++i)  
			f=f*i; //求 c!
		sum += f; //此时sum的值为a!+b!+c!
		if(sum==n)  //若条件成立,则 n 就是要找的数。
			cout<<n<<"  ";  
		++n;  //考察下一个n
    }  
    return 0;  
}  

  方法归纳:在这一类题目中,常要对某一范围内的所有数进行考察,以便列出其中符合某条件的所有数。需要逐个考察相应范围内的每一个数字。因此,程的顶层结构是:
for(n=下限;n<=上限;n+=增量) //增量不一定固定为1  
{  
   为构造条件进行相关的计算;  
   if(条件成立) 输出符合要求的结果  
}  

例如,要处理的数是所有三位数中的偶数,对应的代码是:
for(n=100;n<1000; n+=2) 
{  
   ……
}  

  任务:解决下面的问题(同样,选做一道即算完成任务)
  (1)输入一个正整数,判断其是否为一个素数。
  (2)输出1000以内的所有素数。
  (3)输入一个正整数,判断其是否为一个回文数(例1221、12321都是回文数)。
  (4)输出10000以内的所有回文数。
  (5)输出10000以内的所有回文素数(提醒:某数是素数后再判断是否也是回文数。);
  (6)若一个素数的反序数仍为素数,则称为可逆素数。求10000以内的所有可逆素数。
  (7)求1000000以内的正整数n,9n是n的反序数(例如,123是321的反序数)。
  (8)阿姆斯特朗数:如果一个正整数等于其各个数字的立方和,则称该数为阿姆斯特朗数(亦称为自恋性数)。如 407=43+03+73就是一个阿姆斯特朗数。试编程求1000以内的所有阿姆斯特朗数。
  (9)亲密数:如果整数A的全部因子(包括1,不包括A本身)之和等于B;且整数B的全部因子(包括1,不包括B本身)之和等于A,则将整数A和B称为亲密数。求3000以内的全部亲密数。(提示:按照亲密数定义,要判断数a是否有亲密数,只要计算出a的全部因子的累加和为b,再计算b的全部因子的累加和为n,若n等于a则可判定a和b是亲密数。)
  (10)很有趣的一个题目:2011年11月02日是一个回文日:2011 1102,在2011级同学做这道题时我们刚刚度过这一天!请列出近80年和近60年还有多少个回文日(假如我们能活到百岁,你和我的……)。注意:一年只有12个月。

【项目4:大奖赛计分】

  在歌星大奖赛中,有10个评委为参赛的选手打分,分数为1~100分。选手最后得分为:去掉一个最高分和一个最低分后其余8个分数的平均值。请编写一个程序实现。
  【项目4扩展1(选做)】大奖赛编的计分程序,成绩在0-10之间,输入错误时要能马上重新输入,选手最后得分为:去掉一个最高分和一个最低分。评委人数(图中为7)需要在在程序开始运行时输入(这比固定10个评委的程序更有适应性了)。
  【项目4扩展2(选做)】在扩展1基础上,输出当前选手的最后得分后,提示“按任意键计算下一位选手的成绩,退出请选择N:”如果输入的不是N或n,可以为下一位选手计算成绩。运行结果如图所示。

  
  如果完成了扩展2,再次体会:如果一个“复杂”任务难于直接完成,可以先完成核心的“简单”任务,再逐渐扩充、完善。

【项目5-体验文件操作】

  先阅读《文件操作初体验》。文件english.dat(含10000个数据的文件在BB平台。为方便校外读者,本文后附100个数据,自行复制粘贴到记事本中保存为文件english.dat))中给出的是2012级10000名新生入学英语分级考试全校同学的成绩。编程序,求出这次考试的平均成绩,并统计各分数段的人数(优秀:≥90,良好:≥80,中等:≥70,及格:≥60,不及格:<60)。运行结果如图所示。

  
  提示:本任务完成困难,可以考虑预做下面的练习
  练习1:从文件中读出学生的成绩,输出最高、最低,以及平均成绩(平均成绩为小数)。
  练习2:从文件中读出学生的成绩,统计90分以上学生的人数并输出。
  拓展1:将输出界面改良下,显示成下面的样子(仅变输出方式)

  
  拓展2:将统计结果保存到数据文件statictic.dat中(提示:要写入文件了)


附:本文后附100个数据,自行复制粘贴到记事本中保存为文件english.dat,以便于完成练习。

66
77
97
65
69
79
79
77
69
74
90
73
64
69
69
69
74
71
83
96
87
88
62
76
65
51
66
73
77
78
73
52
78
75
73
60
69
56
76
68
76
77
87
56
61
62
69
64
73
68
62
62
79
88
79
77
71
57
88
69
71
78
74
67
86
55
86
78
81
52
66
67
68
85
72
74
84
64
61
76
71
64
91
72
82
60
70
64
84
75
67
67
85
70
59
72
87
65
55
77



  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

迂者-贺利坚

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值