算法与程序实践1简单计算文档格式.docx
《算法与程序实践1简单计算文档格式.docx》由会员分享,可在线阅读,更多相关《算法与程序实践1简单计算文档格式.docx(25页珍藏版)》请在冰豆网上搜索。
![算法与程序实践1简单计算文档格式.docx](https://file1.bdocx.com/fileroot1/2023-1/22/3d409079-3280-4fd9-b2b6-67e1c9e0e1d3/3d409079-3280-4fd9-b2b6-67e1c9e0e1d31.gif)
课堂练习:
CS1、CS2、CS3
课堂讲解:
CS4(CS5)
A类(满分80)课堂练习:
CS8、CS9、CS10
B类(满分100)课堂上机:
CS11、CS20
斐波那契数列
问题描述:
已知斐波那契数列第n项的计算公式如下。
在计算时有两种算法:
递归和非递归,请分别给出这两种算法。
当n=0时,Fib(n)=0,当n=1时,Fib(n)=1,当n>
1时,Fib(n)=Fib(n-1)+Fib(n-2)
输入:
第一行是测试数据的组数m,后面跟着m行输入。
每行包括一个项数n和一个正整数a。
(m,n,a均大于0,且均小于10000000)
输出:
输出包含m行,每行对应一个输入,若a不大于Fib(n),则输出Yes,否则输出No
输入样例:
3
33
1050
2420000
输出样例:
No
Yes
参考程序1(zzg):
循环版
#include<
stdio.h>
intmain()
{
intfn2,fn1,fn,m,n,a,i,j;
fn2=0;
fn1=1;
//freopen("
in.txt"
"
r"
stdin);
out.txt"
w"
stdout);
scanf("
%d"
&
m);
for(i=1;
i<
=m;
i++)
{
scanf("
%d%d"
n,&
a);
if(n==1)
{
if(a<
=fn1)
printf("
Yes\n"
);
else
No\n"
}
else
for(j=2;
j<
=n;
j++)
{
fn=fn2+fn1;
fn2=fn1;
fn1=fn;
if(a<
=fn)
{
printf("
break;
}
}
if(j>
n)
}
return1;
}
递归版(zzg)
intfib(intn)
if(n<
2)
returnn==0?
0:
1;
else
returnfib(n-2)+fib(n-1);
intm,n,a,i,j;
for(j=1;
=fib(j))
break;
if(j>
printf("
注意事项:
这题主要考察递归与非递归的用法,还有数值越界的情况。
1)测试数据可取一下11和13试一下。
2)测试数据可以取一下501000和10001000。
程序中若考虑到值的越界就没问题或者考虑使用break也可以。
正整数解
求x2+y2=2000的正整数解,输出所有不同的解。
参考程序:
math.h>
intx,y,m;
m=(int)sqrt(2000);
for(x=1;
x<
x++)
for(y=x;
y<
y++)
if(x*x+y*y==2000)
%d*%d+%d*%d=2000\n"
x,x,y,y);
return0;
这题主要考察枚举的用法,还有求平方根(数学函数)的用法。
1)要考虑x和y可调换,所以需要加上y>
=x,这样就能保证不会出现重复的解
2)考虑一下优化的问题for(y=x;
y++)可以优化为:
for(y=m;
y>
=x;
y--),甚至还可以
inttemp=(int)sqrt(2000-x*x)
for(y=temp;
y--)
鸡兔同笼
(来源:
2750)
一个笼子里面关了鸡和兔子(鸡有2只脚,兔子有4只脚,没有例外)。
已经知道了笼子里面脚的总数a,问笼子里面至少有多少只动物,至多有多少只动物。
第1行是测试数据的组数n,后面跟着n行输入。
每组测试数据占1行,包括一个正整数a(a<
32768)。
n行,每行输出对应一个输入。
输出是两个正整数,第一个是最少的动物数,第二个是最多的动物数,两个正整数用空格分开。
如果没有满足要求的情况出现,则输出2个0。
2
20
00
510
intnCase,nFeet,i;
nCase);
=nCase;
nFeet);
if(nFeet%2!
=0)
00\n"
elseif(nFeet%4!
=0)
%d%d\n"
nFeet/4+1,nFeet/2);
nFeet/4,nFeet/2);
解题思路:
这个问题可以描述成任给一个整数N,如果N是奇数,输出00,否则如果N是4的倍数,输出N/4,N/2,如果N不是4的倍数,输出N/4+1,N/2。
这是一个一般的计算题,只要实现相应的判断和输出代码就可以了。
题目中说明了输入整数在一个比较小的范围内,所以只需要考虑整数运算就可以了。
这里考察数学计算,出错有一下几种情况:
1)因为对问题分析不清楚,给出了错误的计算公式;
2)不用数学方法,而试图用枚举所有鸡和兔的个数来求解此题,造成超时;
3)试图把所有输入先存储起来,再输出,开的数组太小,因数组越界产生运行错;
4)在每行输出末尾缺少换行符;
5)对输入输出语法不熟悉导致死循环或语法错。
棋盘上的距离
1657)
国际象棋的棋盘是黑白相间的8*8的方格,棋子放在格子中间。
如图1-1所示:
图1-1国际象棋棋盘
王、后、车、象的走子规则如下:
王:
横、直、斜都可以走,但每步限走一格。
后:
横、直、斜都可以走,每步格数不受限制。
车:
横、竖均可以走,不能斜走,格数不限。
象:
只能斜走,格数不限。
写一个程序,给定起始位置和目标位置,计算王、后、车、象从起始位置走到目标位置所需的最少步数。
第一行是测试数据的组数t(0<
=t<
=20)。
以下每行是一组测试数据,每组包括棋盘上的两个位置,第一个是起始位置,第二个是目标位置。
位置用"
字母-数字"
的形式表示,字母从“a”到“h”,数字从“1”到“8”。
输出要求:
对输入的每组测试数据,输出王、后、车、象所需的最少步数。
如果无法到达,就输出“Inf”。
输入样例
a1c3
f5f8
输出样例
2121
311Inf
解题思路
这个问题是给定一个棋盘上的起始位置和终止位置,分别判断王、后、车、象从起始位置到达终止位置需要的步数。
首先,王、后、车、象彼此独立,分别考虑就可以了。
所以这个题目重点要分析王、后、车、象的行走规则特点,从而推出它们从起点到终点的步数。
我们假设起始位置与终止位置在水平方向上的距离是x,它们在竖直方向上的距离是y。
根据王的行走规则,它可以横、直、斜走,每步限走一格,所以需要的步数是min(x,y)+abs(x-y),即x,y中较小的一个加上x与y之差的绝对值。
根据后行走的规则,她可以横、直、斜走,每步格数不受限制,所以需要的步数是1(x等于y或者x等于0或者y等于0)或者2(x不等于y)。
根据车行走的规则,它可以横、竖走,不能斜走,格数不限,需要步数为1(x或者y等于0)或者2(x和y都不等于0)。
根据象行走得规则,它可以斜走,格数不限。
棋盘上的格点可以分为两类,第一类是它的横坐标和纵坐标之差为奇数,第二类是横纵坐标之差为偶数。
对于只能斜走的象,它每走一步,因为横纵坐标增加或减小的绝对值相等,所以横坐标和纵坐标之差的奇偶性无论如何行走都保持不变。
因此,上述的第一类点和第二类点不能互相到达。
如果判断出起始点和终止点分别属于两类点,就可以得出它们之间需要无数步的结论。
如果它们属于同一类点,象从起始点走到终止点需要1(x的绝对值等于y的绝对值)或者2(x的绝对值不等于y的绝对值)。
校门外的树木
2808)
某校大门外长度为L的马路上有一排树,每两棵相邻的树之间的间隔都是1米。
我们可以把马路看成一个数轴,马路的一端在数轴0的位置,另一端在L的位置;
数轴上的每个整数点,即0,1,2,……,L,都种有一棵树。
由于马路上有一些区域要用来建地铁。
这些区域用它们在数轴上的起始点和终止点表示。
已知任一区域的起始点和终止点的坐标都是整数,区域之间可能有重合的部分。
现在要把这些区域中的树(包括区域端点处的两棵树)移走。
你的任务是计算将这些树都移走后,马路上还有多少棵树。
输入的第一行有两个整数L(1<
=L<
=10000)和M(1<
=M<
=100),L代表马路的长度,M代表区域的数目,L和M之间用一个空格隔开。
接下来的M行每行包含两个不同的整数,用一个空格隔开,表示一个区域的起始点和终止点的坐标。
输出包括一行,这一行只包含一个整数,表示马路上剩余的树的数目。
5003
150300
100200
470471
输出样例:
298
这个问题可以概括为输入一个大的整数闭区间,及一些可能互相重叠的在该大区间内的小的整数闭区间。
在大的整数闭区间内去除这些小的整数闭区间,问之后剩下的可能不连续的整数区间内有多少个整数。
这个题目给出的范围是大的区间在1~10000以内,要去除的小的区间的个数是100个以内。
因为规模较小,所以可以考虑用空间换时间,用一个大数组来模拟这些区间,数组中的每个数表示区间上的一个数。
例如,如果输入L的长度是500,则据题意可知最初有501棵树。
我们就用一个501个元素的数组来模拟这501棵树,数组的下标分别代表从1到501棵树,数组元素的值代表这棵树是否被一走。
最初这些树都没有被移走,所以所有数组元素的值都用true来表示。
每当输入一个小区间,就将这个区间对应的树全部移走,即将这个区间对应的数组元素下标指示的元素的值置成false。
如果有多个区间对应同一个数组元素,会导致多次将某个数组元素置成false。
不过这并不影响结果的正确性。
当所有小区间输入完成,我们可以数一下剩下的仍旧为true的元素的个数,就可以得到最后剩下的树的数目。
当然如果最开始输入的区间不是500,则我们使用的数组大小就不是500。
因为题目给出的上限是10000,所以我们可以定义一个大小是10001个元素的数组,这样对所有输入都是够用的。
思考题:
如果马路长度L的值极大,比如是40亿,以至于无法开设这么大的trees数组,本题该如何解决?
填词
2801)
Alex喜欢填词游戏。
填词游戏是一个非常简单的游戏。
填词游戏包括一个N*M大小的矩形方格盘和P个单词。
然后需要把每个方格中填上一个字母使得每个单词都能在方格盘上被找到。
每个单词都能被找到要满足下面的条件:
每个方格都不能同时属于超过一个的单词。
一个长为k的单词一定要占据k个方格。
单词在方格盘中出现的方向只能是竖直的或者水平的(可以由竖直转向水平,反之亦然)。
你的任务是首先在方格盘上找到所有的单词,当然在棋盘上可能有些方格没有被单词占据。
然后把这些没有用的方格找出来,把这些方格上的字母按照字典序组成一个“神秘单词”。
如果你还不了解规则,我们可以用一个例子来说明,比如在图1-2中寻找单词BEG和GEE。
图1-2填词游戏方格盘
输入的第一行包括三个整数N,M和P(2<
=M,N<
=10,0<
=P<
=100)。
接下来的N行,每行包括M个字符来表示方格盘。
接下来P行给出需要在方格盘中找到的单词。
输入保证填词游戏至少有一组答案。
输入中给出的字母都是大写字母。
输出要求
输出“神秘单词”,注意“神秘单词”中的字母要按照字典序给出。
332
EBG
GEE
EGE
BEG
输出样例
EEG
题目中给出的条件比较隐晦。
输入中给出的字母都是大写字母——表明输出也只能是大写字母。
输入保证填词游戏至少有一组答案——这说明我们不必寻找单词所在的位置,只要去掉这些单词所占用的字母就可以了。
“神秘单词”中的字母要按照字典序给出——说明我们只要知道“神秘单词”中的字母组成就可以了,在字母组成确定的情况下,按字典序输出的方式只有一种。
分析到这里我们发现这其实是个很简单的问题。
给出一个字母的集合,从中去掉一些在给出单词中出现过的字母,将剩下的字母按字典序输出!
可以定义一个有26个元素的数组,分别记录在输入的矩形中,每个字母出现的次数,当读入单词时,将数组中对应到单词中的字母的元素值减一。
处理完所有的单词后,将数组中的非0的元素对应的字母依次输出,数组元素的值是几,就输出几次该字母。
装箱问题
1017)
一个工厂制造的产品形状都是长方体,它们的高度都是h,长和宽都相等,一共有六个型号,他们的长宽分别为1*1,2*2,3*3,4*4,5*5,6*6.这些产品通常使用一个6*6*h的长方体包裹包装然后邮寄给客户。
因为邮费很贵,所以工厂要想方设法的减小每个订单运送时的包裹数量。
他们很需要有一个好的程序帮他们解决这个问题从而节省费用。
现在这个程序由你来设计。
输入文件包括几行,每一行代表一个订单。
每个订单里的一行包括六个整数,中间用空
格隔开,分别为1*1至6*6这六种产品的数量。
输入文件将以6个0组成的一行结尾。
除了输入的最后一行6个0以外,输入文件里每一行对应着输出文件的一行,每一行输
出一个整数代表对应的订单所需的最小包裹数。
004001
751000
000000
1
这个问题描述得比较清楚,我们在这里只解释一下输入输出样例:
共有两组有效输入,第一组表示有4个3*3的产品和一个6*6的产品,此时4个3*3的产品占用一个箱子,另外一个6*6的产品占用1个箱子,所以箱子数是2;
第二组表示有7个1*1的产品,5个2*2的产品和1个3*3的产品,我们可以把他们统统放在一个箱子中,所以输出是1。
分析六个型号的产品占用箱子的具体情况如下:
6*6的产品每个会占用一个完整的箱子,并且没有空余空间;
5*5的产品每个占用一个新的箱子,并且留下11个可以盛放1*1的产品的空余空间;
4*4的产品每个占用一个新的箱子,并且留下5个可以盛放2*2的产品的空余空间;
3*3的产品情况比较复杂,首先3*3的产品不能放在原来盛有5*5或者4*4的箱子中,那么必须为3*3的产品另开新的箱子,新开的箱子数目等于3*3的产品的数目除以4向上取整;
同时我们需要讨论为3*3的产品新开箱子时,剩余的空间可以盛放多少2*2和1*1的产品(这里如果有空间可以盛放2*2的产品,我们就将它计入2*2的空余空间,等到2*2的产品全部装完,如果还有2*2的空间剩余,再将它们转换成1*1的剩余空间)。
我们可以分情况讨论为3*3的产品打开的新箱子中剩余的空位,共为四种情况:
第一种,3*3的产品的数目正好是4的倍数,所以没有空余空间;
第二种,3*3的产品数目是4的倍数加1,这时还剩5个2*2的空位和7个1*1的空位;
第三种,3*3的产品数目是4的倍数加2,这时还剩3个2*2的空位和6个1*1的空位;
第四种,3*3的产品数目是4的倍数加3,这时还剩1个2*2的空位和5个1*1的空位;
处理完3*3的产品,就可以比较一下剩余的2*2的空位和2*2产品的数目,如果产品数目多,就将2*2的空位全部填满,再为2*的产品打开新箱子,同时计算新箱子中1*1的空位,如果剩余空位多,就将2*2的产品全部填入2*2的空位,再将剩余的2*2的空位转换成1*1的空位;
最后处理1*1的产品,比较一下1*1的空位与1*1的产品数目,如果空位多,将1*1的产品全部填入空位,否则,先将1*1的空位填满,然后再为1*1的产品打开新的箱子。
求平均年龄
2714)
班上有学生若干名,给出每名学生的年龄(整数),求班上所有学生的平均年龄,保留到小数点后两位。
第一行有一个整数n(1<
=n<
=100),表示学生的人数。
其后n行每行有1个整数,取值为15到25。
输出一行,该行包含一个浮点数,为要求的平均年龄,保留到小数点后两位。
样例输入:
18
17
样例输出:
17.50
提示:
要输出浮点数、双精度数小数点后2位数字,可以用下面这种形式:
printf("
%.2f"
num);
数字求和
2796)
给定一个正整数a,以及另外的5个正整数,问题是:
这5个整数中,小于a的整数的和是多少?
输入一行,只包括6个小于100的正整数,其中第一个正整数就是a。
输出一行,给出一个正整数,是5个数中小于a的数的和。
10123411
10
两倍
2807)
给定2到15个不同的正整数,你的任务是计算这些数里面有多少个数对满足:
数对中一个数是另一个数的两倍。
比如给定1432971822,得到的答案是3,因为2是1的两倍,4是2个两倍,18是9的两倍。
输入包括多组测试数据。
每组数据包括一行,给出2到15个两两不同且小于100的正整数。
每一行最后一个数是0,表示这一行的结束后,这个数不属于那2到15个给定的正整数。
输入的最后一行只包括一个整数-1,这行表示输入数据的结束,不用进行处理。
对每组输入数据,输出一行,给出有多少个数对满足其中一个数是另一个数的两倍。
14329718220
248100
751113130
-1
肿瘤面积
2713)
在一个正方形的灰度图片上,肿瘤是一块矩形的区域,肿瘤的边缘所在的像素点在图片中用0表示。
其它肿瘤内和肿瘤外的点都用255表示。
现在要求你编写一个程序,计算肿瘤内部的像素点的个数(不包括肿瘤边缘上的点)。
已知肿瘤的边缘平行于图像的边缘。
只有一个测试样例。
第一行有一个整数n,表示正方形图像的边长。
其后n行每行有n个整数,取值为0或255。
整数之间用一个空格隔开。
已知n不大于1000。
输出一行,该行包含一个整数,为要求的肿瘤内的像素点的个数。
5
255255255255255
255000255
25502550255
肿瘤检测
2677)
一张CT扫描的灰度图像可以用一个N*N(0<
N<
100)的矩阵描述,矩阵上的每个点对应一个灰度值(整数),其取值范围是0-255。
我们假设给定的图像中有且只有一个肿瘤。
在图上监测肿瘤的方法如下:
如果某个点对应的灰度值小于等于50,则这个点在肿瘤上,否则不在肿瘤上。
我们把在肿瘤上的点的数目加起来,就得到了肿瘤在图上的面积。
任何在肿瘤上的点,如果它是图像的边界或者它的上下左右四个相邻点中至少有一个是非肿瘤上的点,则该点称为肿瘤的边界点。
肿瘤的边界点的个数称为肿瘤的周长。
现在给定一个图像,要求计算其中的肿瘤的面积和周长。
输入第一行包含一个正整数N(0<
100),表示图像的大小;
接下来N行,每行包含图像的一行。
图像的一行用N个整数表示(所有整数大于等于0,小于等于255),两个整数之间用一个空格隔开。
输出只有一行,该行包含两个正整数,分别为给定图像中肿瘤的面积和周长,用一个空格分开。
6
999999999999
999999509999
999949495051
995020255299
405099999999
98
垂直直方图
2800)
输入4行全部由大写字母组成的文本,输出一个垂直直方图,给出每个字符出现的次数。
注意:
只用输出字符的出现次数,不用输出空白字符,数字或者标点符号的输出次数。
输入包括4行由大写字母组成的文本,每行上字符的数目不超过80个。
输出包括若干行。
其中最后一行给出26个大写英文字母,这些字母之间用空格隔开。
前面的几行包括空格和星号,每个字母出现几次,就在这个字母的上方输出一个星号。
输出的第一行不能是空行。
THEQUICKBROWNFOXJUMPEDOVERTHELAZYDOG.
THISISANEXAMPLETOTESTFORY