号:  3192052

桂林理工大学

GUILIN UNIVERSITY OF TECHNOLOGY

   程序设计实践课程     

课程设计与实习报告

      信息科学与工程学院 #

            计算机类      

      级:         

      生:           

指导教师                   

  分/价                    

                         

                                

                                

2020年 11 月 13 日

目录

第一部分:基础问题

  1. 显示数字出现次数···························································3

1.2 显示Pascal三角形··························································4

1.3 计算到任意日期的总天数·················································6

1.4 字符统计······································································8

1.5 不一样的汉诺塔···························································10

1.6 周游世界····································································12

1.7 最强阵容····································································13

1.8 朋友··········································································15

1.9 矿工安全生产······························································18

1.10 字母塔······································································19

第二部分:选做题

2.1 整数因子分解问题························································21

2.2 选择问题····································································22

2.3 贪心算法····································································24

2.4 最长公共子串问题························································26

2.5 哈夫曼树····································································28

第三部分:ACM实践题

3.1 Financial Management···················································31

3.2 Digital Roots································································34

3.3 Prime·········································································37

3.4 Gizilch········································································39

3.5 Sequence·····································································44

部分:心得体会

·····················································································47

部分:外文翻译

·····················································································48

  1. 基础实践部分

    1. 显示数字出现次数

输入一个十进制正整数,转换成16进制数。再输入一个数(0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f),统计这个数出现的次数。

【输入格式】

一行输入十进制正整数。 另一行输入要统计的数。

【输出格式】

要统计的数出现的次数。

【输入样例】

在这里给出一组输入。例如:

84117512

8

【输出样例】

3

  1. 程序题目描述

题目要求我们输入一个十进制的整数并将其转换成十六进制数;再输入一个整数,找出该整数在上面转化出的十六进制的各位数出现的次数。

(2)总体设计思想

首先输入一个十进制的正整数n,后跟一个while语句,其判断条件是当十进制正整数n不为零时,执行while内的语句:对十进制正整数n除以16求余,将求得的余数存入数组a中,再对n除以16求商,继续while语句知道n为零;输入要统计的数r,遍历数组a找到与r相同的数字并统计其出现的次数k,遍历结束后输出k。

(3)代码

#include<stdio.h>

#define N 100

int main()

{

int n;//n为一个十进制的正整数

int a[N];

int p=-1;//数组a的下标

int k=0;//要统计的数出现的次数

int r;

scanf("%d",&n);//输入一个十进制的正整数

while(n!=0)//求n的十六进制数

{

a[++p]=n%16;//求得余数存入a数组中

n=n/16;

}

scanf("%d",&r);//要统计的数

for(int i=0;i<=p;i++)

{

if(r==a[i])

k++;//要统计的数出现的次数

}

printf("%d",k);

}

4算法分析

该算法的时间复杂度为O(n),空间复杂度为O(n)。

5运行结果

  1. 显示Pascal三角形

输入行数n,显示n行Pascal三角形。数字间有一个空格。每行最后一个数字后有一个空格。

【输入格式】

在一行中输入行数n。

【输出格式】

输出n行Pascal三角形。

【输入样例】

在这里给出一组输入。例如:

4

【输出样例】

在这里给出相应的输出。例如:

1

1 1

1 2 1

1 3 3 1

(1)程序题目描述

题目要求我们设计算法输入一个正整数,该正整数即为行数,输出对应行数的Pascal三角形。

(2)总体设计思想

首先,定义一个二维数组和整型n(行数),输入行数,用for语句遍历二维数组并使其对角线上的数都为1;再使用for语句使对角线下每一个数都为其上面的数与左上角的数的和,最后输出该二维数组即为题目所求。

(3)代码

#include<stdio.h>

#define N 100

int main()

{

int i,j,n;

int a[N][N];

scanf("%d",&n);//输入行数n

for(i=0;i<n;i++)

for(j=0;j<=i;j++)

{

if(i==0||j==i)//让Pascal三角形的斜边数都为1

a[i][j]=1;

else

a[i][j]=a[i-1][j]+a[i-1][j-1];//上面的数加上左上的数

}

for(i=0;i<n;i++)

for(j=0;j<=i;j++)

{

if(i!=j)

printf("%d ",a[i][j]);

else

printf("%d \n",a[i][j]);//若果i=j则输出a[i][j](每行最后一个数字)后带一空格并换行

}

printf("\n");

}

4算法分析

该算法的时间复杂度为O(n2),空间复杂度为O(n2)。

5运行结果

  1. 计算到任意日期的总天数

编程序实现:输入任意一个日期的年、月、日的值,求出从公元1年1月1日到该日期前一年的年末总共有多少天,到该日期前一个月的月末总共有多少天,到这一天总共有多少天。假定从公元第一天开始,就实施格里高利历法。格里高利历法的置闰规则是400年97闰,也可以概括为:四闰百不闰,四百闰。

【输入格式】

输入三个代表年、月、日的正整数,以空格分隔。

【输出格式】

输出三个总天数,数据之间以换行符分隔,最后换行。

【输入样例】

2012 3 29

【输出样例】

734502

734562

734591

(1)程序题目描述

题目要求我们输入一个日期,计算从公园1年1月1日到该日前前一年末、前一月末和到这一天总共各有多少天。

  1. 总体设计思想

首先使用for语句计算从公园一年到该日期的前一年(不包括输入的日期的年份)共有多少个平年和多少个闰年;用if语句判断输入的年份是否为闰年,后用switch语句计算从该年年初到该月的前月末共有多少天,最后所求到前年末的天数即为闰年年数乘以366加上平年年数加上365;其他类似。

  1. 代码

#include<stdio.h>

#define N 100

int main()

{

int s;//s为m1个月有多少天

int r=0,p=0;

int y=1,m=1,d=1;//公园111

int y1,m1,d1;//输入的年月日

int n1,n2,n3;//结果 前年末 前月末 当天

scanf("%d%d%d",&y1,&m1,&d1);

for(int i=1;i<y1;i++)//年

{

if((i%4==0&&i%100!=0)||i%400==0)//闰年:能被4整除而不能被100整除 或者能被400整除

r++;//闰年个数

else

p++;//平年个数

}

if((y1%4==0&&y1%100!=0)||y1%400==0)//月(是闰年)

switch(m1-1)//m1-1表示只计算到前一月月末

{

case 0:s=0;break;

case 1:s=31;break;

case 2:s=60;break;

case 3:s=91;break;

case 4:s=121;break;

case 5:s=152;break;

case 6:s=182;break;

case 7:s=213;break;

case 8:s=244;break;

case 9:s=274;break;

case 10:s=305;break;

case 11:s=335;break;

case 12:s=366;break;

}

else//如果是平年

switch(m1-1)

{

case 0:s=0;break;

case 1:s=31;break;

case 2:s=59;break;

case 3:s=90;break;

case 4:s=120;break;

case 5:s=151;break;

case 6:s=181;break;

case 7:s=212;break;

case 8:s=243;break;

case 9:s=273;break;

case 10:s=304;break;

case 11:s=334;break;

case 12:s=365;break;

}

n1=r*366+p*365;//前年末

n2=r*366+p*365+s;//前月末

n3=r*366+p*365+s+d1;//当天

printf("%d\n",n1);

printf("%d\n",n2);

printf("%d\n",n3);

}

4算法分析

该算法的时间复杂度为O(n)。

5运行结果

  1. 字符统计

请编写程序,找出一段给定文字中出现最频繁的那个英文字母。

【输入格式】

输入在一行中给出一个长度不超过 1000 的字符串。字符串由 ASCII 码表中任意可见字符及空格组成,至少包含 1 个英文字母,以回车结束(回车不算在内)。

【输出格式】

在一行中输出出现频率最高的那个英文字母及其出现次数,其间以空格分隔。如果有并列,则输出按字母序最小的那个字母。统计时不区分大小写,输出小写字母。

【输入样例】

This is a simple TEST.  There ARE numbers and other symbols 1&2&3...........

【输出样例】

e 7

(1)程序题目描述

题目要求我们输入一行字符串,统计字符串中出现最频繁的字母,输出该字母的小写以及该字母出现的次数。

(2)总体设计思想

首先将字符串输入数组a中,用for语句遍历该数组,遇到大写字母就将其转化成小写字母,将每一个字母对应的ASCII值为数组sum的下标,遍历到一某个字母便在数组sum75对应位置加一;最后遍历数组sum找到数组中最大的数,输出该数,将该最大数的下标转换成小写字母输出。

(3)代码

#include<stdio.h>

int main()

{ int i;

int max=0,max_i,s=0;

//max某字母出现最频繁的次数,max_i为该字母(小写输出)

char a[1001]={0};

int sum[26]={0};

gets(a);//输入字符串

for(i = 0;a[i]!='\0';i++)

{

if(a[i]>='A'&&a[i]<='Z')

{

a[i]=a[i]+'a'-'A';//将大写字母转变为小写

s=a[i]-97;//s为a[i]下标(97为a的ASCII值

sum[s]++;  //该字母出现一次则在数组sum对应的位置+1

}

else if(a[i]>='a'&&a[i]<='z')

{

s=a[i]-97;

sum[s]++;

}

}

for(i=0;i<26;i++)

{

if(sum[i]>max)

{

max=sum[i];

//找到数组sum中的最大值即为出现最频繁的字母出现的次数

max_i=i;

}

}

printf("%c %d\n",max_i+'a',max);//max_i+'a'转换为字母(小写)

}

4算法分析

该算法的时间复杂度为O(n)。

5运行结果

  1. 不一样的汉诺塔

相传在古印度圣庙中,有一种被称为汉诺塔(Hanoi)的游戏。该游戏是在一块铜板

装置上,有三根杆(编号A、B、C),在A杆自下而上、由大到小按顺序放置若干金盘(如下图)。

游戏的目标:把A杆上的金盘全部移到C杆上,并仍保持原有顺序叠好。

操作规则:每次只能移动一个盘子,并且在移动过程中三根杆上都始终保持大盘在下,小盘在上,操作过程中盘子可以置于A、B、C任一杆上。

事实上,汉诺塔游戏中的行动可以这样看待:当你需要移动某个盘子的时候,你需要先将它上面的全部盘子移动到无关杆上,再将这个盘子移动到目标杆,然后将它上面的盘子从无关杆移动到目标杆。从而,这一问题就可以通过递归的方式解决了。现在题目给出起始杆上按规律码放的盘子数量,请你给出将它们移动到目标杆上所需的最少步数。

【输入格式】

一个正整数N(N<5000),代表你需要移动的的盘子数。

【输出格式】

一个正整数,代表最少需要的步数。

【输入样例】

70

【输出样例】

1180591620717411303423

提示:

如遇WA,请注意输入数据的范围。

(1)总体设计思想

在主函数调用一个递归函数,再在调用的函数里调用该函数将盘子依次移动。

(2)代码

#include<stdio.h>

int k=0;

int hanoi(int n,char x,char y,char z)//x,y,z代表A杆、B杆、C杆

{

if(n==1)

printf("");//若n为1 则不进行移动

else

{

//递归移动

hanoi(n-1,x,z,y);//将n-1个盘从x借助z移动到y

hanoi(n-1,y,x,z);//将n-1个盘从y借助x移动到z

}

k++;//移动次数

}

int main()

{

int N;

scanf("%d",&N);//少需要的步数N

hanoi(N,'A','B','C');//A杆、B杆、C杆

printf("%d\n",k);

}

3算法分析

该算法的时间复杂度为O(2n)。

4运行结果

  1. 周游世界

周游世界是件浪漫事,但规划旅行路线就不一定了…… 全世界有成千上万条航线、铁路线、大巴线,令人眼花缭乱。所以旅行社会选择部分运输公司组成联盟,每家公司提供一条线路,然后帮助客户规划由联盟内企业支持的旅行路线。本题就要求你帮旅行社实现一个自动规划路线的程序,使得对任何给定的起点和终点,可以找出最顺畅的路线。所谓“最顺畅”,首先是指中途经停站最少;如果经停站一样多,则取需要换乘线路次数最少的路线。

【输入格式】

输入在第一行给出一个正整数N(≤100),即联盟公司的数量。接下来有N行,第i行(i=1,⋯,N)描述了第i家公司所提供的线路。格式为:

M S[1] S[2] ⋯ S[M]

其中M(≤100)是经停站的数量,S[i](i=1,⋯,M)是经停站的编号(由4位0-9的数字组成)。这里假设每条线路都是简单的一条可以双向运行的链路,并且输入保证是按照正确的经停顺序给出的——也就是说,任意一对相邻的S[i]S[i+1]i=1,⋯,M−1)之间都不存在其他经停站点。我们称相邻站点之间的线路为一个运营区间,每个运营区间只承包给一家公司。环线是有可能存在的,但不会不经停任何中间站点就从出发地回到出发地。当然,不同公司的线路是可能在某些站点有交叉的,这些站点就是客户的换乘点,我们假设任意换乘点涉及的不同公司的线路都不超过5条。

在描述了联盟线路之后,题目将给出一个正整数K(≤10),随后K行,每行给出一位客户的需求,即始发地的编号和目的地的编号,中间以一空格分隔。

【输出格式】

处理每一位客户的需求。如果没有现成的线路可以使其到达目的地,就在一行中输出“Sorry, no line is available.”;如果目的地可达,则首先在一行中输出最顺畅路线的经停站数量(始发地和目的地不包括在内),然后按下列格式给出旅行路线:

Go by the line of company #X1 from S1 to S2.

Go by the line of company #X2 from S2 to S3.

......

其中Xi是线路承包公司的编号,Si是经停站的编号。但必须只输出始发地、换乘点和目的地,不能输出中间的经停站。题目保证满足要求的路线是唯一的。

【输入样例】

4

7 1001 3212 1003 1204 1005 1306 7797

9 9988 2333 1204 2006 2005 2004 2003 2302 2001

13 3011 3812 3013 3001 1306 3003 2333 3066 3212 3008 2302 3010 3011

4 6666 8432 4011 1306

4

3011 3013

6666 2001

2004 3001

2222 6666

【输出样例】

2

Go by the line of company #3 from 3011 to 3013.

10

Go by the line of company #4 from 6666 to 1306.

Go by the line of company #3 from 1306 to 2302.

Go by the line of company #2 from 2302 to 2001.

6

Go by the line of company #2 from 2004 to 1204.

Go by the line of company #1 from 1204 to 1306.

Go by the line of company #3 from 1306 to 3001.

Sorry, no line is available.

  1. 程序题目描述

(2)总体设计思想

(3)代码

  1. 算法分析
  2. 运行结果
    1. 最强阵容

拿着新换来的英雄卡,小李满心欢喜的准备和同学们PK一下。 他们的游戏规则非常简单,双方把自己的牌绕成一圈,然后指定一个起点,从该张牌开始顺时针方向往后取,谁取出的字符串字典序更小(从左到右开始比较,碰到第一个不一样的字符进行比较,比较规则为a<b<…<z)谁将获得胜利。具体规则可参考样例。虽然现在小李的牌已经很好了,但是你能不能帮他快速算出起始位置,使得他能够派出最强阵容。

【输入格式】

第一行n,表示共有n张牌。 第二行共n个用一个空格隔开的小写字母,表示给定的一圈牌起始序列。

【输出格式】

仅一个整数,能获得最小字典序字符串的起点位置。如果有多个位置开始的字符串一样,则输出最小的那个位置,且第一个位置从1开始。

【输入样例】

4

b c a b

【输出样例】

3

(1)程序题目描述

题目要求我们输入n个用空格隔开的小写字母表示一圈牌,找出字符串典序最小的序列并输出。

(2)总体设计思想

首先输入以空格隔开的n个字母,后用while语句一个一个字母判断字母串的典序大小,找到字母典序最小的序列时,该序列的起始字母所在位置即是题目所求。

(3)代码

#include<stdio.h>

int main()

{

int n;//n张牌

char ch,s[1000];

int k=-1;//数组s的下标

scanf("%d",&n);

getchar();//取走回车键

while(k!=n)

{

ch=getchar();//输入字母,以空格隔开

if(ch!=' ')

{

k++;

s[k]=ch;//将字母存入数组s中

}

if(k==n)//结束while循环

break;

}

int t;

int i=0,j=1,p=0;

while(i<n&&j<n&&p<n)

{

t=s[(i+p)>=n?i+p-n:i+p]-s[(j+p)>=n?j+p-n:j+p];//t=s[0]-s[1]=b-c

if(!t)//b-c

p++;//p=1

else

{

if(t>0)

i=i+p+1;

else

j=j+p+1;

if(i==j)

++j;

p=0;

}

}

printf("%d",(i<j?i:j)+1);

}

4算法分析

该算法的时间复杂度为O(n),空间复杂度为O(n)。

5运行结果

  1. 朋友

【问题描述】 同学们应该学会多交一些好朋友。朋友关系是相互的,A是B的好朋友,则B也是A 的好朋友。朋友关系是不传递的,A是B的好朋友,B是C的好朋友,但A和C不一定是 好朋友。现在给出某小学部分同学之间的朋友关系,请编程统计朋友最多的人有多少个好 朋友。

【输入数据】

输入共m+1行。

第1行是两个整数nm,分别表示同学总人数和朋友关系对数。

第2行到第m+1行,描述了m对朋友关系。每行两个用单个空格隔开的同学姓名。

每个人的姓名仅由小写字母组成,且1≤姓名的长度≤10

【输出数据】

一个整数,表示朋友最多的人有多少个好朋友。

【输入输出样例1】

4 3

lucy lily

jam lily

jam peter

2

【样例1解释】

4个人,3对朋友关系。

lucy只有一个朋友lily;

jam 有两个朋友lily和peter;

lily有两个朋友lucy和jam;

peter只有一个朋友jam。

所以lily和jam 朋友最多,都是2个。

【输入输出样例2】

6 5

andy bob

bella andy

bob andy

andy cassie

cassie bob

3

【样例2解释】

6个人,5对朋友关系。其中第1对朋友关系“andy bob”和第3对朋友关系“bob andy” 重复。

andy有三个朋友,分别是bob、bella和cassie;

bob有两个朋友andy和cassie;

bella只有一个朋友andy;

cassie有两个朋友bob和andy;

另外2个人没有朋友(这两个人在输入中没有出现)。

所以andy的朋友最多,有3个朋友。

【数据范围约定】 50%以上的测试点输入数据保证朋友关系没有重复。 100%的测试点输入数据保证2≤n≤100,1≤m≤1000,且没有自己跟自己的朋友关系。

(1)程序题目描述

题目要求我们输入n个人和m对朋友关系,找出这些人中朋友最多的人,输出他的朋友数目。

(2)总体设计思想

首先用for语句在主函数输入一对朋友,调用trans函数将名字记录并转换为数组下标,返回主函数后用if语句判断输入的该对朋友是否重复,把个名字出现的次数各记录到数组对应位置,最后遍历数组找到最大的数即为朋友最多的人的朋友对数。

(3)代码

#include<stdio.h>

#include<string.h>

char a[11];

int p=-1,b[110],c[110][110];//数组b用来保存这些名字出现的次数

int trans(char s) //转换为数组下标

{

for(int i=0;i<p;i++)

{

if(s==a[i])//如果s=已存入数组a中的名字

return i;//返回在主函数 跳出trans函数

}

a[p++]=s;

return p-1;

}

int main()

{

int n,m,i;

scanf("%d%d",&n,&m);//同学总人数n,关系对数m(行)

char s1[11],s2[11];//名字1,名字2

for(i=0;i<m;i++)

{

scanf("%s%s",&s1,&s2);//输入一对名字

int k1=trans(*s1);//0 2

int k2=trans(*s2);// 1 1

if(c[k1][k2]==0&&c[k2][k1]==0) //判断这一对名字有没有出现过

{

b[k1]++;//1

b[k2]++;//1

c[k1][k2]=c[k2][k1]=1;

}

}

int max=0;

for(i=0;i<n;i++)

{

if(b[i]>max)//找数组b中数字最大的即为题目所求

max=b[i];

}

printf("%d\n",max);

return 0;

}

4算法分析

该算法的时间复杂度为O(n),空间复杂度为O(n)。

5运行结果

  1. 矿工安全生产

有一座地下的稀有金属矿由n条隧道和一些连接点组成,其中每条隧道连接两个连接点。任意两个连接点之间最多只有一条隧道。为了降低旷工的危险,你的任务是在一些连接点处安装太平井和相应的逃生装置,使得不管哪个连接点倒塌,不在此连接点的所有旷工都能到达太平井逃生(假定除了倒塌的连接点不能通行外,其他隧道和连接点完好无损)。为了节约成本,你应当在尽量少的连接点安装太平井。还需要计算出当太平井的数量最小时的安装方案总数。

【输入格式】

输入包含多组数据。每组数据第一行为隧道的条数n(n<=50000),以下n行每行两个整数,即一条隧道两端的连接点编号(所有连接点从1开始编号)。每组数据的所有连接点保证连通。以0表示输入结束。

【输出格式】

对于每组数据,输出两个整数,即最少需要安装的太平井数目以及对应的方案总数。方案总数保证在64位带符号整数的范围内。

【输入样例】

9

1 3

4 1

3 5

1 2

2 6

1 5

6 3

1 6

3 2

6

1 2

1 3

2 4

2 5

3 6

3 7

0

【输出样例】

2 4

4 1

(1)程序题目描述

(2)总体设计思想

建立一个连通图,使图的某个节点删除时该节点依然与其它节点相连。

(3)代码

(4)算法分析

(5)运行结果

  1. 字母塔

请编写程序,显示字母塔。

【输入格式】

行数(正整数,不超过26)

【输出格式】

显示指定行数的字母塔

【输入样例】

6

【输出样例】

a

aba

abcba

abcdcba

abcdedcba

abcdefedcba

(1)程序题目描述

题目要求我们输入一个正整数然后输出字母塔,正整数为字母塔的行数(不超过26);要求输出的字母塔为一个等腰三角形,每行有2n-1个字母。

(2)总体设计思想

首先输入行数n,后用for语句将字母塔的每一行输出。

(3)代码

#include<stdio.h>

int main()

{

int n,i,j;

char letter='a';

scanf("%d",&n); //输入行数

for(i=1;i<=n;i++)

{

for(j=1;j<=n-i;j++)

putchar(' '); //每行输出n-i个空格

for(j=i;j>=1;j--)

putchar(letter+i-j); //输出第i行的字母(输出只到每行中间数),输出时从a开始字母次序增加

for(j=2;j<=i;j++)

putchar(letter+i-j);//输出第i行后半部分的字母,字母次序依次减小直到 a

printf("\n");

}

}

4算法分析

该算法的时间复杂度为O(n2)。

5运行结果

  1. 选做题

    1. 分治与递归  

整数因子分解问题:大于1的正整数n可以分解为:

例如若n=12,共用8种不同的分解式:

对于给定的正整数n,编程计算n有多少种不同的分解式。

【输入】:数据有多行,给出正整数n

【输出】:每个数据输出一行,是正整数n的不同的分解式数量。

【输入样例】:

12

35

【输入样例】

8

3

(1)程序题目描述

题目要求我们输入多个正整数,输出每个正整数的分解式的数量。

(2)总体设计思想

首先使用一个while循环输入正整数,在while语句里调用一个对输入的正整数进行因式分解的函数,将你能够进行因式分解的次数记录并返回主函数输出。

(3)代码

#include <stdio.h>

int Decom(int n)

{

int i;

int count=0;

if (n==1)

return 1;//将1返回主函数,跳出Decom函数

else

for (i=2;i<=n;i++)

{

//i从2开始到n本身 ,若n能被i整除,则count+1

if (n%i==0)

count+=Decom(n/i);

}

return count;

}

int main()

{

int n,count;

while (scanf("%d",&n)) //输入正整数n

{

if(n!=0)

{

count=Decom(n);

printf("%d\n",count);

}

else//n为0时结束循环

break;

}

return 0;

}

4算法分析

该算法的时间复杂度为O(n)。

5运行结果

  1. 选择问题

给定的n个元素数组a[0: n-1],要求找出第k小的元素。

【输入】

输入多组测试例:对于每一个测试例有两行,第一行是整数n和k, 第二行是n个整数

【输出】

第k小的元素

【输入样例】

5  2

3  9  4  1  6

7  3

4  59  7  23  61  55  46

【输出样例】

3

23

(1)总体设计思想

首先使用while语句输入多组数据,对每组数据的第二行存在一数组中,并将其从小到大进行排序,最后遍历排好序的数组找到第k个数即为题目所求。

(2)代码

#include<stdio.h>

#define N 100

int main()

{

int n,k,temp;

int a[N];

while(k!=0)//当k不为0时

{

scanf("%d%d",&n,&k);

for(int s=0;s<n;s++)

scanf("%d",&a[s]);//每行n个整数

for(int i=0;i<n;i++)//先将该行的整数从小到大排序

{

for(int j=i+1;j<n;)

{

if(a[i]>a[j])

{

temp=a[i];

a[i]=a[j];

a[j]=temp;

j++;

}

else

j++;

}

}

printf("%d\n",a[k-1]);//输出数组中下标为k-1的数即为该行整数第k小的元素

}

}

3算法分析

该算法的时间复杂度为O(n2),空间复杂度为O(n)。

4运行结果

  1. 贪心算法

多处最优服务次序问题

假设n个顾客同时等待一项服务,顾客i需要的服务时间为ti,共有s处可以提供此服务。应如何安排n个顾客的服务次序才能使得平均等待时间达到最小?平均等待时间是n个顾客等待服务时间的总和除以n。

对于给定的n个顾客需要的服务时间和s的值,编程计算最优的服务次序。

【输入】

第一行有两个正整数n和s,表示n个顾客和s处可以为顾客提供需要的服务。

接下来的一行中,有n个正整数,表示n个顾客需要的服务时间。

【输出】

最小平均等待时间,保留三位小数

【输入样例】

10  2

56  12  1  99  1000  234  33  55  99  812

【输出样例】

336.00

(1)程序题目描述

题目要求我们输入两个正整数分别代表顾客数目和提供服务处的数目,后接一行每个顾客所需要服务的时间,通过算法设计求出顾客的平均等待时间。

(2)总体设计思想

首先输入n个顾客和s处服务处,输入每个顾客的服务时间(存入一个数组中),输入顾客服务时间时把顾客的服务时间相加得到的就是所有顾客的服务时间;用if语句计算出每个顾客的等待时间后加和,最后加上顾客的总服务时间再除以顾客数目即为题目所求。

(3)代码

#include<stdio.h>

#define N 100

int main()

{

int n,s,i,j,k,temp;

int ser=0;//所有顾客等待的总时间

int ti[N],p[N],q[N];//ti等待时间,

scanf("%d%d",&n,&s);//n个顾客,s处可供服务

for(i=0;i<n;i++)

{

scanf("%d",&ti[i]);// 输入每个顾客等待的时间

ser+=ti[i];//n个顾客服务时间总和

}

for(j=0;j<n;j++)//将n个顾客的等待时间从小到大排序

for(k=j+1;k<n;k++)

{

if(ti[k]<ti[j])

{

temp=ti[j];

ti[j]=ti[k];

ti[k]=temp;

}

}

j=0;

k=0;

while(j<n)

{

if(j<s)

{

p[k]=0;// 第一个和第二个顾客等待时间为0

q[k]=0;

j++;//1 2

k++;//1 2

}

else

{

p[k]=p[k]+ti[j-s];

q[k]=q[k]+p[k];//某人的等待时间等于前一个人(p[k])的等待时间

j++;

k++;

}

if(k==s)

k=0;

}

int wait=0;

double count;

for(j=0;j<s;j++)

{

wait+=q[j];//加和所有人的等待时间

}

count=(wait+ser)/n;//等待时间+服务时间再除以人数

printf("%.2f",count);

}

4算法分析

该算法的时间复杂度为O(n2),空间复杂度为O(n)。

5运行结果

  1. 最长公共子串问题

假设有两个字符串(可能包含空格),找出其中最长的公共连续子串,并输出其长度。

输入描述:

输入为两行字符串(可能包含空格),长度均小于等于50

输出描述:

输出为一个整数,表示最长公共连续子串的长度

输入例子:

abcde

abgde

输出例子:

2

ab

de

(1)程序题目描述

题目要求我们输入两行字符串,判断它们的最长公共连续子串,输出其长度。

(2)总体设计思想

首先输入另个字符串,用for语句对两个字符串中的字符进行比较,找出最长的连续公共子串,输出其长度。

(3)代码

#include<stdio.h>

#include<string.h>

#define N 50

int main()

{

char s1[N],s2[N];

char c[N][N];

int max=0;// 最长公共连续子串的长度

int i,j;

gets(s1);//输入第一个字符串

gets(s2);//输入第二个字符串

for(i=0;i<strlen(s1);i++)

{

/*一个一个比较字母是否相同,相同则c[i][j]+1,若c[i][j]+1比max大,

则最长公共连续子串的长度max=c[i][j] */

for(j=i;j<strlen(s2);j++)

{

if(s1[i]==s2[j])

{

if(i>0&&j>0)

{

c[i][j]=c[i-1][j-1]+1;

}

else

{

c[i][j]=1;

}

if(max<c[i][j])

{

max=c[i][j];

}

}

}

}

printf("%d\n",max); //输出长公共连续子串的长度

}

4算法分析

该算法的时间复杂度为O(n),空间复杂度为O(n2)。

5运行结果

  1. 哈夫曼树

Huffman树在编码中有着广泛的应用。在这里,我们只关心Huffman树的构造过程。

给出一列数{pi}={p0, p1, …, pn-1},用这列数构造Huffman树的过程如下:

1. 找到{pi}中最小的两个数,设为pa和pb,将pa和pb从{pi}中删除掉,然后将它们的和加入到{pi}中。这个过程的费用记为pa + pb。

2. 重复步骤1,直到{pi}中只剩下一个数。

在上面的操作过程中,把所有的费用相加,就得到了构造Huffman树的总费用。

本题任务:对于给定的一个数列,现在请你求出用该数列构造Huffman树的总费用。

例如,对于数列{pi}={5, 3, 8, 2, 9},Huffman树的构造过程如下:

1. 找到{5, 3, 8, 2, 9}中最小的两个数,分别是2和3,从{pi}中删除它们并将和5加入,得到{5, 8, 9, 5},费用为5。

2. 找到{5, 8, 9, 5}中最小的两个数,分别是5和5,从{pi}中删除它们并将和10加入,得到{8, 9, 10},费用为10。

3. 找到{8, 9, 10}中最小的两个数,分别是8和9,从{pi}中删除它们并将和17加入,得到{10, 17},费用为17。

4. 找到{10, 17}中最小的两个数,分别是10和17,从{pi}中删除它们并将和27加入,得到{27},费用为27。

5. 现在,数列中只剩下一个数27,构造过程结束,总费用为5+10+17+27=59。

【输入格式】

输入的第一行包含一个正整数n(n<=100)。

接下来是n个正整数,表示p0, p1, …, pn-1,每个数不超过1000。

【输出格式】

输出用这些数构造Huffman树的总费用。

【样例输入】

5

5 3 8 2 9

【样例输出】

59

(1)程序题目描述

题目要求我们输入n个正整数,找出n个正整数中最小的两个数相加,把加和后的数放回,再继续找出最小的两个数重复上述操作,最后只剩下一个数时即为题目所求。

(2)总体设计思想

首先输入n个正整数存入数组中,遍历数组找到最小的数记录其下标,将该数在数组中的值赋值为MAX,再遍历数组找到最小的数记录其位置,将第一个最小的数与第二个最小的数相加后再加入数组中,继续上述步骤,当寻找的第二个最小的数等于MAX时,说明该数组只剩下一个数,结束循环,输出该数。

(3)代码

#include <stdio.h>

#define MAX 1000//每个数最大不能超过1000

int main()

{

int n;//n<=100

scanf("%d",&n);//n个正整数

int p[n];

for(int i=0;i<n;i++)

{

scanf("%d",&p[i]);//输入n个正整数

}

int sum=0,m=1;

int flag;

int min1=MAX,min2=MAX;

while(m)

{

for(int i=0;i<n;i++)

{

if(p[i]<min1)//遍历数组p找到第一个最小的数

{

min1=p[i];

flag=i;//标记该最小的数的下标

}

}

p[flag]=MAX;//找到第一个最小的数让它在数组中的值等于MAX

for(int j=0;j<n;j++)

{

if(p[j]<min2)

{

min2=p[j];//遍历数组p找到第二个最小的数

flag=j; // 标记该数

}

}

p[flag]+=min1;//找到第二个最小的与第一个最小的min1相加后再加入到p数组中

if(min2==MAX)//如果min2=MAX说明数组中只剩下一个数,结束循环

{

break;

}

else

{

sum+=min1+min2;//将两个最小的数相加

min1=MAX;

min2=MAX;

}

}

printf("%d",sum);

return 0;

}

4算法分析

该算法的时间复杂度为O(n2),空间复杂度为O(n)。

5运行结果

  1. ACM实践题

    1. Financial Management(财务管理1004

Financial Management

Time Limit: 1000MS

Memory Limit: 10000K

Total Submissions: 220516

Accepted: 83219

Description

Larry graduated this year and finally has a job. He's making a lot of money, but somehow never seems to have enough. Larry has decided that he needs to grab hold of his financial portfolio and solve his financing problems. The first step is to figure out what's been going on with his money. Larry has his bank account statements and wants to see how much money he has. Help Larry by writing a program to take his closing balance from each of the past twelve months and calculate his average account balance.

Input

The input will be twelve lines. Each line will contain the closing balance of his bank account for a particular month. Each number will be positive and displayed to the penny. No dollar sign will be included.

Output

The output will be a single number, the average (mean) of the closing balances for the twelve months. It will be rounded to the nearest penny, preceded immediately by a dollar sign, and followed by the end-of-line. There will be no other spaces or characters in the output.

Sample Input

100.00

489.12

12454.12

1234.10

823.05

109.20

5.27

1542.25

839.18

83.99

1295.01

1.75

Sample Output

$1581.42

原题翻译:

拉里今年毕业,终于找到了工作。他赚了很多钱,但不知怎么的,似乎总是不够。拉里决定,他需要抓住他的金融投资组合,解决他的融资问题。第一步是弄清楚他的钱到底怎么了。拉里有他的银行账户对账单,想看看他有多少钱。帮助拉里编写一个程序,从过去12个月的每个月中提取期末余额,并计算出他的平均账户余额。

输入:

输入将是12行。每一行将包含他银行账户在特定月份的期末余额。每一个数字都是正数,并显示为便士。不包括美元符号。

输出:

产出将是一个单一的数字,即12个月期末余额的平均值。它将四舍五入到最接近的一分钱,前面紧跟着一个美元符号,然后是行尾。输出中将没有其他空格或字符。

样本输入:

100.00

489.12

12454.12

1234.10

823.05

109.20

5.27

1542.25

839.18

83.99

1295.01

1.75

样本输出:

$1581.42

(1)程序题目描述

题目要求我们输入拉里过去12个月每个月的月末余额,输出12个月月末余额的平均值。

(2)总体设计思想

首先使用for语句输入拉里过去12个月的月末余额,将12个月的雨墨余额加和,再除以12即为其平均值,输出时保留两位小数。

(3)代码

#include<stdio.h>

int main()

{

double m,sum,ave;

int i;

for(i=0;i<12;i++)//12个月 (12行)

{

scanf("%lf",&m);//过去12个月的每个月中的期末余额

sum+=m;// 将过去12个月的每个月中的期末余额相加

}

ave=sum/12;//求每月平均值

printf("$%.2lf\n",ave);

}

4算法分析

该算法的时间复杂度为O(12)。

5运行结果

    1. Digital roots(数字根1519)

Digital Roots

Time Limit: 1000MS

Memory Limit: 10000K

Total Submissions: 28671

Accepted: 9413

Description

The digital root of a positive integer is found by summing the digits of the integer. If the resulting value is a single digit then that digit is the digital root. If the resulting value contains two or more digits, those digits are summed and the process is repeated. This is continued as long as necessary to obtain a single digit.

For example, consider the positive integer 24. Adding the 2 and the 4 yields a value of 6. Since 6 is a single digit, 6 is the digital root of 24. Now consider the positive integer 39. Adding the 3 and the 9 yields 12. Since 12 is not a single digit, the process must be repeated. Adding the 1 and the 2 yeilds 3, a single digit and also the digital root of 39.

Input

The input file will contain a list of positive integers, one per line. The end of the input will be indicated by an integer value of zero.

Output

For each integer in the input, output its digital root on a separate line of the output.

Sample Input

24

39

0

Sample Output

6

3

原题翻译:

正整数的数字根是通过对整数的位数求和得到的。如果得到的值是个位数,那么这个数字就是数字根。如果结果值包含两个或两个以上的数字,则将这些数字相加并重复此过程。只要需要获得一个位数,就可以继续这样做。

例如,考虑正整数24。加上2和4得到的值是6。因为6是个位数,所以6是24的数字根。现在考虑正整数39。加上3和9得到12。因为12不是一个数字,所以必须重复这个过程。加上1和2是3,一个数字和39的数字根。

输入:

输入文件将包含一个正整数列表,每行一个。输入的结尾将由一个0的整数值表示。

输出:

对于输入中的每个整数,将其数字根输出到单独的输出行上。

样本输入:

24

39

0

样本输出:

6

3

(1)程序题目描述

题目要求我们输入一个正整数,将正整数的位数求和则为该正整数的数字根,若经过一次位数求和之后得到的数大于等于10.则再将这个数的位数求和,得到的数即为正整数的数字根。

(2)总体设计思想

输入多个正整数,当输入0时停止输入(用strcmp函数进行判断),对于每个正整数,测量其长度后用for语句将其位数相加,用while语句判断相加后的数是否大于等于10,若大于或者等于则将其位数相加得到数字根。

(3)代码

#include <stdio.h>

#include <string.h>

int main()

{

char str[10000];

while (scanf("%s",&str))

{

int root=0;

if (strcmp(str,"0")==0)

{

break;

}

int len=strlen(str);

for (int i=0;i<len;i++)

{

root+=str[i]-'0';//将str[i]转换成对应ASCII中的数字进行计算

}

while (root>=10)

{

int temp=root;

root=0;//root归零

while (temp>0)

{

root+=temp%10;

temp/=10;

}

}

printf("%d\n",root);

}

}

4算法分析

该算法的时间复杂度为O(n2)。

5运行结果

    1. Prime(质数3978)

Primes

Time Limit: 1000MS

Memory Limit: 65536K

Total Submissions: 5949

Accepted: 2104

Description

A pretty straight forward task, calculate the number of primes between 2 integers.

Given 2 integers A ≤ B < 105 what’s the number of primes in range from A to B inclusive.

Note: A prime number is a positive integer greater than 1 and is divisible by 1 and itself only. For N to be prime it is enough to test the divisibility of numbers less than or equal to square root of N.

Input

As many as 1000 lines, each line contains 2 integers A and B separated by a space. Input is terminated when A = B = -1 (Do not process this line).

Output

For every line in input – except for the last line where A = B = -1 - print the number of prime numbers between A and B inclusive.

Sample Input

0 9999

1 5

-1 -1

Sample Output

1229

3

原题翻译:

一个相当直接的任务,计算两个整数之间的素数。

给定两个整数A≤B<10^5,那么从A到B范围内的素数是多少。

注:质数是一个大于1的正整数,只能被1和它自己整除。对于N是素数,只要检验小于或等于N的平方根的数的整除性就足够了。

输入:

多达1000行,每行包含两个整数A和B,用空格隔开。输入在A=B=-1时终止(不处理此行)。

输出:

对于输入中的每一行,除了最后一行A=B=-1-打印A和B之间的质数(包括A和B)。

样本输入:

0   9999

1   5

-1  -1

样本输出:

1229

3

(1)程序题目描述

题目要求我们输入多行整数,每行有一对用空格隔开的整数,求出在这两个整数范围内的质数的个数。

(2)总体设计思想

首先在主函数用while语句输入判断质数的范围,当输入的两个数为-1时停止输入;输入一组整数后调用一个判断质数的函数,在该函数用for语句i从2开始到该整数的平方根,判断该整数是否能被i整除,如果能则返回主函数使sum+1,最后输出sum。

(3)代码

#include<stdio.h>

#include<math.h>

int prime(int N)//判断是否为质数

{

if(N<=0||N==1)

return false;

for(int i=2;i<=sqrt((double)N);i++)

{

//sqrt为求平方根函数;将n强制转换成double型后求平方根

if(N%i==0)

return false;

}

return true;

}

int main()

{

int A,B;

int sum;

while(true)

{

sum=0;

scanf("%d%d",&A,&B);//输入两个整数

if(A==-1&&B==-1)//当这两个整数为-1时结束循环

break;

for(int i=A;i<=B;i++)//在A到B范围内

if(prime(i))

++sum;

printf("%d\n",sum);

}

}

4算法分析

该算法的时间复杂度为O(n2)。

5运行结果

    1. Gizilch(小精灵1078)

Gizilch

Time Limit: 1000MS

Memory Limit: 10000K

Total Submissions: 1856

Accepted: 713

Description

The game of gizilch has very simple rules. First 100 grapes are labeled, in nontoxic ink, with the numbers 1 to 100. Then, with a cry of ``GIZILCH!'', the referee fires the grapes up into the air with a giant gizilcher. The two players, who each start with a score of ``1'', race to eat the falling (or, shortly thereafter, fallen) grapes and, at the same time, multiply their scores by the numbers written on the grapes they eat. After a minute, the hungry squirrels are let loose to finish the remaining grapes, and each contestant reports his score, the product of the numbers on the grapes he's eaten. The unofficial winner is the player who announces the highest score. 
Inevitably, though, disputes arise, and so the official winner is not determined until the disputes are resolved. The player who claims the lower score is entitled to challenge his opponent's score. The player with the lower score is presumed to have told the truth, because if he were to lie about his score, he would surely come up with a bigger better lie. The challenge is upheld if the player with the higher score has a score that cannot be achieved with grapes not eaten by the challenging player. So, if the challenge is successful, the player claiming the lower score wins.

So, for example, if one player claims 343 points and the other claims 49, then clearly the first player is lying; the only way to score 343 is by eating grapes labeled 7 and 49, and the only way to score 49 is by eating a grape labeled 49. Since each of two scores requires eating the grape labeled 49, the one claiming 343 points is presumed to be lying.

On the other hand, if one player claims 162 points and the other claims 81, it is possible for both to be telling the truth (e.g. one eats grapes 2, 3 and 27, while the other eats grape 81), so the challenge would not be upheld.

Unfortunately, anyone who is willing to referee a game of gizilch is likely to have himself consumed so many grapes (in a liquid form) that he or she could not reasonably be expected to perform the intricate calculations that refereeing requires. Hence the need for you, sober programmer, to provide a software solution.

Input

Pairs of unequal, positive numbers, with each pair on a single line, that are claimed scores from a game of gizilch.

Output

Numbers, one to a line, that are the winning scores, assuming that the player with the lower score always challenges the outcome.

Sample Input

343 49

3599 610

62 36

Sample Output

49

610

62

Hint

A clarification was made at the beginning of the contest to resolve some ambiguity in the problem description noticed a couple of days before the contest. The rules for deciding the winner of a game of gizilch are, first, if both players might be telling the truth, the larger score wins. Second, if the player with the lower score cannot be telling the truth, the player with the higher score wins. Finally, if neither of the previous two conditions holds, the lower score wins..

原题翻译:

小精灵的游戏规则很简单。前100个葡萄用无毒墨水标记,数字为1到100。然后,伴随着“小精灵”的叫声,裁判员用一个巨大的小精灵把葡萄升到空中。这两名选手的得分都是“1”,他们竞相吃掉掉下来的(或不久之后,又掉下来的)葡萄,同时将他们的分数乘以他们吃的葡萄上写的数字。一分钟后,饥饿的松鼠被放出来吃剩下的葡萄,每个参赛者都会报告自己的分数,即他所吃葡萄上数字的乘积。非官方的赢家是宣布最高分数的选手。

不过,不可避免地会出现争议,因此在争议解决之前,官方的赢家是不会确定的。声称得分较低的选手有权挑战对手的得分。得分较低的球员被认为说了实话,因为如果他对自己的分数撒谎,他肯定会说出一个更大更好的谎言。如果得分较高的选手有一个不能用葡萄来达到的分数,那么挑战被支持。因此,如果挑战成功,则声称得分较低的玩家获胜。

所以,举个例子,如果一个玩家声称343分,另一个玩家声称49分,那么显然第一个玩家是在撒谎;要想获得343分,唯一的办法就是吃标签为7和49的葡萄,而获得49分的唯一方法就是吃标签为49的葡萄。由于两个分数中的每一个都需要食用标签为49的葡萄,所以声称343分的葡萄被认为是在撒谎。

另一方面,如果一个玩家声称162分,另一个玩家声称81分,那么两个玩家都有可能说的是实话(比如一个吃葡萄2、3和27,而另一个吃葡萄81),所以挑战不会被支持。

不幸的是,任何一个愿意为小精灵游戏做裁判的人都有可能自己吃了太多葡萄(以液体形式存在),因此无法合理地期望他或她执行裁判所需的复杂计算。因此需要你,冷静的程序员,提供一个软件解决方案。

输入:

一对不相等的正数,每对在一条线上,声称是从一个小发明游戏中得到的分数。

输出:

一对一的数字,就是获胜的分数,假设得分低的选手总是挑战结果。

样本输入:

343  49

3599  610

62  36

样本输出:

49

610

62

(1)程序题目描述

题目要求我们输入多行正整数对,设计算法判断正整数对中数较小的是否总存在一种分解,是数较大的总有的因子,如果是则输出较小的数。

(2)总体设计思想

首先在主函数使用while语句,输入多对整数,对于每对整数找出较小的数,调用一个dfs函数对其进行因式分解,在dfs函数里再调用dfs函对数较大的进行因式分解,若数较小的是否总存在一种分解,是数较大的总有的因子,则返回主函数输出数较小的,否则输出数值较大的。

(3)代码

#include<stdio.h>

#include<string.h>

int min,max;

int visited,visite;

int a[101];

int dfs(int score)//深度搜索

{

int s,i;

if(score==1)

{

if(visited==0)

{

visited=1;

visite=1;

if(dfs(max)==1)

return 1;

else

{

visited=0;

return 0;

}

}

return 1;

}

if(score>100)

s=100;

else

s=score;

for(i=2;i<=s;i++)//对score进行因式分解

{

if(score%i==0&&a[i]==0)

{

a[i]=1;

if(dfs(score/i)==1)

return 1;

a[i]=0;

}

}

return 0;

}

int main()

{

int score1,score2,result,winner,i;

while(scanf("%d%d",&score1,&score2) != EOF)//Ctrl+z结束循环

{

visited=visite=0;

for(i=0;i<101;i++)

a[i]=0;

//判断分数较小者为挑战者

if(score1>score2)

{

min=score2;

max=score1;

}

else

{

min=score1;

max=score2;

}

result=dfs(min); /*对分数较小者进行因式分解

若分数较小者总存在一种分解,是分数较大者总有的因子,

则说明被挑战者说谎,挑战者胜利 */

if(visited==1&&result==1||visite==0)

winner=max;

else

winner=min;

printf("%d\n",winner);

}

return 0;

}

4算法分析

该算法的时间复杂度为O(n100),空间复杂度为O(n)。

5运行结果

    1. Sequence序列2313

Sequence

Time Limit: 1000MS

Memory Limit: 65536K

Total Submissions: 4183

Accepted: 1639

Description

Given a sequence with N integers A(1), A(2), ..., A(N), your task is to find out a sequence B(1), B(2), ..., B(N), such that

V = (|A(1) – B(1)| + |A(2) – B(2)| + ... + |A(N) – B(N)|) + (|B(1) – B(2)| + |B(2) – B(3)| + ... +|B(N-1) – B(N)|)is minimum.

Input

The first line in the input contains an integer N (1 <= N <= 100). Then follow N lines, the i-th of which contains an integer A(i) (-10000 <= A(i) <= 10000).

Output

The output only contains an integer, which is the minimum value of V.

Sample Input

3

3

5

8

Sample Output

5

原图翻译:

给定一个包含N个整数a(1)、a(2)、…、a(N)的序列,您的任务是找出序列B(1)、B(2)、…、B(N),这样

V=(| A(1)–B(1)|+| A(2)–B(2)|+。。。+| A(N)–B(N)|+(| B(1)–B(2)|+| B(2)–B(3)|+。。。+|B(N-1)–B(N)|)

是最小值。

输入:

输入中的第一行包含整数N(1<=N<=100)。然后跟随N行,其中第i行包含整数A(i)(-10000<=A(i)<=10000)。

输出:

输出仅包含一个整数,即V的最小值。

样本输入:

3

3

5

8

样本输出:

5

(1)程序题目描述

题目要求我们输入一个整数N,后输入N行整数A(i),设计算法使V=(| A(1)–B(1)|+| A(2)–B(2)|+…+| A(N)–B(N)|+(| B(1)–B(2)|+| B(2)–B(3)|+…+|B(N-1)–B(N)|)是最小值。

(2)总体设计思想

首先将N个整数输入数组a中,使数组b[1]=a[1],b[N]=a[N],用for语句遍历数组a,判断数组a中的数与数组b的关系,最后得出的数组b能使V=(| A(1)–B(1)|+| A(2)–B(2)|+…+| A(N)–B(N)|+(| B(1)–B(2)|+| B(2)–B(3)|+…+|B(N-1)–B(N)|)是最小值,最后输出v。

  1. 代码

#include<stdio.h>

#include<math.h>

int main()

{

int N,i;

int v=0;

int a[101],b[101];

scanf("%d",&N);

for(i=1;i<=N;i++)//N行,每行输入一个整数

{

scanf("%d",&a[i]);

}

b[1]=a[1];//令数组b[1]等于第一个整数

for(i=2;i<N;i++)

{

if(a[i]>b[i-1]&&a[i]>a[i+1])

{

if(a[i+1]>b[i-1])

b[i]=a[i+1];

else

b[i]=b[i-1];

}

else if(a[i]<b[i-1]&&a[i]<a[i+1])

{

if(a[i+1]<b[i-1])

b[i]=a[i+1];

else

b[i]=b[i-1];

}

else

b[i]=a[i];

}

b[N]=a[N];

for(i=1;i<=N;i++)

{

v=v+fabs(a[i]-b[i]);//fabs为求绝对值函数

}

for(i=2;i<=N;i++)

{

v=v+fabs(b[i-1]-b[i]);

}

printf("%d\n",v);

}

3算法分析

该算法的时间复杂度为O(n),空间复杂度为O(n)。

4运行结果

  1. 心得体会

为期三个星期的程序设计实习已结束,通过自己的努力和与同学的探讨,完成了本次的程序设计实习内容,虽说有些题目完成的不是很完美又或者是说某些题目未能完成,是一个小小的遗憾,但我尽量地把我会做的每一道题完整地完成。

虽然此前我们学习过C语言和数据结构,但当我一开始做题目时,还是会遇到许多的问题,对于此前学习过的知识点稍有些遗忘,所以在每一次做题过程中我都能够把遗忘的知识点捡起;在这过程中还遇到了不少的新问题,我都会就这些新的问题到上网或者是书本上查找答案;在写程序过程中难免地会使用百度进行搜索,很多时候会搜索到与C++相关的内容,因此我在网上自学了一点点较为基础的C++知识,比如说它所用到的头文件如何定义以及它的输入输出所使用的形式等等,但最终编写程序时都还是使用了我们所学习过的C语言;我也因此学到了不少的知识,不仅巩固了我的知识结构,又使我对C语言有了更深一步的了解,掌握了更多的技巧与技能。

这一次的实习使我受益匪浅,不仅学到了新的知识,还锻炼了我的动手能力;让我明白了我所欠缺的不仅仅是技术知识,更是一种处理事情的方法、面对问题的心态和动手能力;在今后,我会更加努力地学习专业知识,锻炼我的实践动手能力,为将来的就业与发展打下基础。

  1.  外文翻译

原文:

Algorithms(B)

When learning your first programming language it is easy to get the impression that the hard part of solving a problem on a computer is translating your ideas into the specific language that will be fed into the computer. This definitely is not the case. The most difficult part of solving a problem on a computer is discovering the method of solution. After you come up with a method of solution, it is routine to translate your method into the required language, be it C++ or some other programming language. It is therefore helpful to temporarily ignore the programming language and to concentrate instead on formulating the steps of the solution and writing them down in plain English, as if the instructions were to be given to a human being rather than a computer. A sequence of instructions expressed in this way is frequently referred to as an algorithm.

A sequence of precise instructions which leads to a solution is called an algorithm. Some approximately equivalent words are recipe, method, directions, procedure, and routine. The instructions may be expressed in a programming language or a human language. Our algorithms will be expressed in English and in the programming language C++. A computer program is simply an algorithm expressed in a language that a computer can understand. Thus, the term algorithm is more general than the term program. However, when we say that a sequence of instructions is an algorithm, we usually mean that the instructions are expressed in English, since if they were expressed in a programming language we would use the more specific term program. An example may help to clarify the concept. Display 1.6 contains an algorithm expressed in rather stylized English. The algorithm determines the number of times a specified name occurs on a list of names. If the list contains the winners of each of last season's football games and the name is that of your favorite team, then the algorithm determines how many games your team won. The algorithm is short and simple but is otherwise very typical of the algorithms with which we will be dealing.

The instructions numbered 1 through 5 in our sample algorithm are meant to be carried out in the order they are listed. Unless otherwise specified, we will always assume that the instructions of an algorithm are carried out in the order in which they are given (written down). Most interesting algorithms do, however, specify some change of order, usually a repeating of some instruction again and again such as in instruction 4 of our sample algorithm.

The word algorithm has a long history. It derives from the name of a 19th century Persian mathematician and astronomer al-Khowarizmi. He wrote a famous textbook on the manipulation of numbers and equations. The book was entitled Kitab al-jabr w’almuqabala, which can be translated as Rules for reuniting and reducing. The similar sounding word algebra was derived from the arabic word aljabr, which appears in the title of the book and which is often translated as reuniting or restoring. The meanings of the words algebra and algorithm used to be much more intimately related than they are today. Indeed, until modern times, the word algorithm usually referred only to algebraic rules for solving numerical equations. Today the word algorithm can be applied to a wide variety of kinds of instructions for manipulating symbolic as well as numeric data. The properties that qualify a set of instructions as an algorithm now are determined by the nature of the instructions rather than by the things manipulated by the instructions. To qualify as an algorithm, a set of instructions must completely and unambiguously specify the steps to be taken and the order in which they are taken. The person or machine carrying out the algorithm does exactly what the algorithm says, neither more nor less.

Program Design

Designing a program is often a difficult task. There is no complete set of rules, no algorithm to tell you how to write programs. Program design is a creative process. Still, there is the outline of a plan to follow. The outline is given in diagrammatic form in Display 1.7. As indicated there, the entire program-design process can be divided into two phases, the problem-solving phase and the implementation phase. The result of the problem-solving phase is an algorithm, expressed in English, for solving the problem. To produce a program in a programming language such as C++, the algorithm is translated into the programming language. Producing the final program from the algorithm is called the implementation phase. The first step is to be certain that the task—that which you want your program to do—is completely and precisely specified. Do not take this step lightly. If you do not know exactly what you want as the output of your program, you may be surprised at what your program produces. Be certain that you know what the input to the program will be and exactly what information is supposed to be in the output, as well as what form that information should be in. For example, if the program is a bank accounting program, you must know not only the interest rate, but also whether interest is to be compounded annually, monthly, daily, or whatever. If the program is supposed to write poetry, you need to determine whether the poems can be in free verse or must be in iambic pentameter or some other meter.

Many novice programmers do not understand the need to design an algorithm before writing a program in a programming language, such as C++, and so they try to short-circuit the process by omitting the problem-solving phase entirely, or by reducing it to just the problem definition part. This seems reasonable. Why not “go for the mark” and save time? The answer is that it does not save time! Experience has shown that the two-phase process will produce a correctly working program faster. The two-phase process simplifies the algorithm design phase by isolating it from the detailed rules of a programming language such as C++. The result is that the algorithm design process becomes much less intricate and much less prone to error. For even a modest size program, it can represent the difference between a half day of careful work and several frustrating days of looking for mistakes in a poorly understood program.

The implementation phase is not a trivial step. There are details to be concerned about, and occasionally some of these details can be subtle, but it is much simpler than you might at first think. Once you become familiar with C++ or any other programming language, the translation of an algorithm from English into the programming language becomes a routine task.

As indicated in Display 1.7, testing takes place in both phases. Before the program is written, the algorithm is tested, and if the algorithm is found to be deficient, then the algorithm is redesigned. That desktop testing is performed by mentally going through the algorithm and executing the steps yourself. On large algorithms this will require a pencil and paper. The C++ program is tested by compiling it and running it on some sample input data. The compiler will give error messages for certain kinds of errors. To find other types of errors, you must somehow check to see if the output is correct.

The process diagrammed in Display 1.7 is an idealized picture of the programdesign process. It is the basic picture you should have in mind, but reality is sometimes more complicated. In reality, mistakes and deficiencies are discovered at unexpected times, and you may have to back up and redo an earlier step. For example, testing the algorithm may reveal that the definition of the problem was incomplete. In such a case you must back up and reformulate the definition. Occasionally, deficiencies in the definition or algorithm may not be observed until a program is tested. In that case you must back up and modify the definition or algorithm and all that follows them in the design process.

翻译:

算法(B)

当你学习第一种编程语言时,很容易产生这样的印象:在计算机上解决一个问题的困难部分是将你的想法翻译成特定的语言,然后输入计算机。当然不是这样。在计算机上解决一个问题最困难的部分是找到解决方法。在你找到解决方法之后,将你的方法翻译成所需的语言,无论是C++还是其他编程语言都是常规的。因此,暂时忽略编程语言是有帮助的,而是集中精力制定解决方案的步骤,并用简单的英语写下来,就好像指令是给人而不是计算机一样。以这种方式表达的指令序列通常被称为算法。

一系列精确的指令导致一个解决方案被称为算法。一些近似等价的词是配方、方法、指导、程序和例行程序。指令可以用编程语言或人类语言表示。我们的算法将用英语和C++语言来表达。计算机程序就是用计算机能理解的语言表达的算法。因此,术语算法比术语程序更通用。然而,当我们说指令序列是一种算法时,我们通常是指指令是用英语表示的,因为如果它们是用编程语言表达的,我们将使用更具体的术语“程序”。一个例子可能有助于阐明这一概念。用英语表达的算法相当程式化。该算法确定指定名称在名称列表中出现的次数。如果列表中包含上赛季每一场足球比赛的胜利者,并且名称是您最喜欢的球队,则算法将确定您的球队赢得了多少场比赛。该算法简短而简单,但在其他方面却是我们将要处理的典型算法。

在我们的示例算法中编号为1到5的指令将按照它们列出的顺序执行。除非另有规定,否则我们将始终假定算法的指令是按照它们被给出(写下来)的顺序执行的。然而,大多数有趣的算法都会指定一些顺序的改变,通常是某条指令一次又一次的重复,比如在我们的示例算法的指令4中。

单词算法有着悠久的历史。它来源于19世纪波斯数学家和天文学家霍瓦里兹米的名字。他写了一本关于数字和方程式运算的著名教科书。这本书名为Kitab al-jabr w'almuqabala,可以翻译为统一和减少的规则。发音相似的单词代数来自阿拉伯语单词aljabr,它出现在书的标题中,通常被翻译为团聚或恢复。代数和算法这个词的含义过去比现在更密切相关。事实上,直到现代,算法这个词通常只指求解数值方程的代数规则。如今,word算法可以应用于各种各样的指令中,用于处理符号数据和数字数据。将一组指令限定为算法的属性现在是由指令的性质决定的,而不是由指令操作的东西决定的。为了符合算法的条件,一组指令必须完全明确地指定要执行的步骤和执行的顺序。执行算法的人或机器完全按照算法所说的去做,既不多也不少。

程序设计:

设计一个程序通常是一项困难的任务。没有一套完整的规则,没有算法告诉你如何编写程序。程序设计是一个创造性的过程。不过,还有一个计划的大纲要遵循。图1.7以图表形式给出了轮廓。如前所述,整个程序设计过程可分为两个阶段,问题解决阶段和实施阶段。问题解决阶段的结果是一个用英语表示的解决问题的算法。为了在C++等编程语言中生成程序,该算法被翻译成编程语言。从算法生成最终程序称为实现阶段。第一步是确定你希望你的程序执行的任务是完全和精确地指定的。不要轻举妄动。如果你不知道你想要什么作为你的程序的输出,你可能会惊讶于你的程序产生了什么。一定要知道程序的输入是什么,输出中应该有什么信息,以及这些信息应该是什么形式。例如,如果这个项目是一个银行会计项目,你不仅要知道利率,还要知道利息是要每年复利、按月复利、按日复利还是其他什么。如果程序应该写诗,你需要确定诗歌是自由诗,还是必须是抑扬格五步格或其他一些韵律。

许多新手程序员不理解在用C++语言编写程序之前需要设计一个算法,所以他们试图通过省略问题求解阶段,或者通过将问题简化为问题定义部分来缩短过程。这似乎是合理的。为什么不“按计划行事”节省时间呢?答案是这不会节省时间!经验表明,两阶段过程将更快地产生一个正确工作的程序。两相过程通过将它与诸如C++之类的编程语言的详细规则隔离来简化算法设计阶段。结果是算法设计过程变得不那么复杂,也不容易出错。即使是一个规模不大的程序,它也可以代表半天的仔细工作和几天令人沮丧的在一个不太了解的程序中寻找错误之间的区别。

实现阶段不是一个微不足道的步骤。有一些细节需要关注,有时这些细节可能是微妙的,但它比你最初想象的要简单得多。一旦你熟悉C++或任何其他编程语言,算法从英语翻译成编程语言就成为日常任务。

如图1.7所示,测试在两个阶段进行。在编写程序之前,对算法进行测试,如果发现算法有缺陷,则重新设计算法。桌面测试是通过在大脑中检查算法并自己执行步骤来执行的。在大型算法中,这需要一支铅笔和一张纸。C++程序通过编译并在一些示例输入数据上运行来测试。对于某些类型的错误,编译器将给出错误消息。要查找其他类型的错误,必须以某种方式检查输出是否正确。

显示1.7中所示的过程图是程序设计过程的理想画面。这是你应该记住的基本图景,但现实有时更复杂。在现实中,错误和缺陷是在意想不到的时候被发现的,您可能需要备份并重新执行之前的步骤。例如,测试算法可能会发现问题的定义是不完整的。在这种情况下,您必须备份并重新制定定义。有时,在程序被测试之前,定义或算法中的缺陷可能不会被观察到。在这种情况下,您必须备份和修改定义或算法以及设计过程中遵循它们的所有内容。

桂林理工大学 2020秋程序设计实践课程 课程设计与实习报告相关推荐

  1. 极客c语言课程设计,c语言课程设计之实习报告共5天完整.doc

    c语言课程设计之实习报告共5天完整 <C语言程序设计> 短学期实习报告 系名:计算机科学与技术系 专业:软件工程 年级:2015级 姓名: <C语言程序设计>短学期实习成绩评定 ...

  2. c语言做一个小程序报告,《C语言程序设计实践》课程报告30个小程序组合成一个大程序.doc...

    北方民族大学 课 程 报 告 课 程 名 称: 程序设计实践 专 业 班 级 : 软件工程(2)班 学 生 姓 名 : 李思良 学 号 : 任 课 教 师 : 王晓锋 学 期 : 2015-2016学 ...

  3. 《python程序设计实践》课程设计报告(胡润百富榜数据爬取及分析)

    1 需求分析 随着科学技术的不断发展,信息流通日益方便,信息数据不断膨胀,充斥在各行各业.由于数据非常庞大,所以即使在搜索引擎存在的情况下,搜索结果的准确率也不高,这使得在网上查找关键有效信息也变为一 ...

  4. 大学计算机作业与实验报告东北农业大学,大学课程数字化测图实习报告.doc

    东北农业大学 实验报告 课程名称: 数字化测图技术 课 程 号: 实验学期:2014-2015学年第一学期 学 院: 资源与环境学院 班 级: 学 号: 实验项目一二三四得 分指导教师总 成 绩姓 名 ...

  5. 桂林理工大学 程序设计实践课程 实习报告

    学  号: 320205205# 桂林理工大学 GUILIN UNIVERSITY OF TECHNOLOGY    程序设计实践课程      实习报告 学      院: 信息科学与工程学院 # ...

  6. 北航计算机组成原理课程设计-2020秋 【系列完结】Verilog或ISE高级特性与自动化测试

    北航计算机学院-计算机组成原理课程设计-2020秋 PreProject-Verilog HDL 与 ISE Verilog或ISE高级特性与自动化测试 本系列所有博客,知识讲解.习题以及答案均由北航 ...

  7. 北航计算机组成原理课程设计-2020秋 PreProject-Verilog HDL与ISE-Verilog工程的设计开发调试

    北航计算机学院-计算机组成原理课程设计-2020秋 PreProject-Verilog HDL 与 ISE Verilog工程的设计开发调试 本系列所有博客,知识讲解.习题以及答案均由北航计算机学院 ...

  8. 北航计算机组成原理课程设计-2020秋 PreProject-入门测试

    北航计算机学院-计算机组成原理课程设计-2020秋 PreProject-入门测试 本系列所有博客,知识讲解.习题以及答案均由北航计算机学院计算机组成原理课程组创作,解析部分由笔者创作,如有侵权联系删 ...

  9. 北航计算机组成原理课程设计-2020秋 PreProject-数制

    北航计算机学院-计算机组成原理课程设计-2020秋 PreProject-数制 本系列所有博客,知识讲解.习题以及答案均由北航计算机学院计算机组成原理课程组创作,解析部分由笔者创作,如有侵权联系删除. ...

  10. 北航计算机组成原理课程设计-2020秋 PreProject-Verilog HDL与ISE-Verilog语法

    北航计算机学院-计算机组成原理课程设计-2020秋 PreProject-Verilog HDL 与 ISE Verilog语法 本系列所有博客,知识讲解.习题以及答案均由北航计算机学院计算机组成原理 ...

最新文章

  1. Hibernate中的核心接口query接口用法
  2. canvas手机端绘图解决方案
  3. 如何联机调试和发布程序(99$)
  4. pom.xml文件第一行报错_Python文件读写指南
  5. Python 实现网络爬虫小程序
  6. Spring Boot基础学习笔记05:Spring Boot多环境配置
  7. Codeup1085: 阶乘的和
  8. SQL PASS西雅图之行——会议篇
  9. 关于Oracle默认用户名system密码不正确登录不上解决方案
  10. c语言修改内存字节,要开学了,小白给大家一个C语言修改dnf内存的示范代码
  11. 实现点击页面报表头某个字段进行该字段的重新排序: 经过验证,此代码是工作的...
  12. MATLAB2016a+eeglab安装
  13. 新萝卜家园 GhostXP SP3 一键极速装机版 2012.05
  14. 惠普HP LaserJet Pro MFP M126nw 打印机驱动
  15. sm是什么职位_职位或职级ED MD SM M 是什么意思?
  16. 2022-02-05大数据学习日志——Hadoop离线阶段——Hive SQL DDL
  17. HTML - 03 网页元素的属性
  18. 读书报告1500字计算机大学篇,大学生读书报告1500.doc
  19. python模拟鼠标拖动滑块_py+selenium拼图式拖动滑块的验证
  20. 360度全景效果图制作步骤是什么?

热门文章

  1. 删除数组中指定元素_删除js数组中的指定元素,有这两步就够了
  2. python中的as是什么意思_python中as用法实例分析
  3. win10X64 + vs2015通过Cmake编译Opencv(一)
  4. 一款好用的日报管理系统“拍了拍”你,手把手教你如何写日报
  5. MySQL做学生考勤系统_Jsp+Ssh+Mysql实现的Java Web学生考勤管理系统
  6. c语言程序设计题库 微盘下载,《C语言程序设计》题库及答案.pdf
  7. 如何重置HDX卡的固件(firmware)
  8. java整蛊小游戏源码_java小游戏源代码
  9. 以下关于java文件名的叙述正确的有_sun java认证考试题库
  10. Jmeter压力测试简单教程(包括服务器状态监控)