scanf("%lf",&a[i]);
Quicksort(a,0,n-1);
printf("%lf",maxtap(a,n));
return0;
5、算法分析:
快速排序的运行时间与划分是否对称有关,其最坏情况发生在划分过程产生的两个区域分别包含n-1个元素和1个元素的时候。
由于函数Partition的计算时间为O(n),所以如果算法Partition的每一步都出现这种不对称划分,则其计算时间复杂性T(n)满足:
解此递归方程可得。
在最好情况下,每次划分所取得基准都恰好为中值,即每次划分都产生两个大小为n/2的区域,此时,Partition的计算时间T(n)满足:
其解为。
可以证明,快速排序算法在平均情况下的时间复杂性也是。
实验三众数问题
1、问题描述:
给定含有n个元素的多重集合S,每个元素在S中出现的次数称为该元素的重数。
多重集S中重数最大的元素称为众数。
例如,S={1,2,2,2,3,5}。
多重集S的众数是2,其重数为3。
对于给定的由n个自然数组成的多重集S,编程计算S的众数及其重数。
2、题目分析:
题目要求计算集合中重复出现最多的数以及该数出现的次数,若两个数出现的次数相同,则取较小的数。
先对集合中的元素从小到大排序,再统计重数,找出最大的重数以及它对应的元素。
3、算法设计:
a.建立数组a[n]存储集合中的元素;
b.调用库函数sort(a,a+n)对集合中的元素从小到大排序;
c.采用for循环依次对排序后的元素进行重数统计:
①用m标记元素,用s统计该元数的重数,分别用max和t标记出现的最大重数和该重数对应的元素。
②若当前元素不同于前一个元素,且前一个元素的重数s>max,更新max和t。
4、源程序:
#include
using?
namespace?
std;
#include
main()
{
int?
n,i,t,m=0,s,max=0,*a;
scanf("%d",&n);
a=new?
int[n];
for(i=0;iscanf("%d",&a[i]);
sort(a,a+n);
for(i=0;i{
if(m!
=a[i])
s=1;
else
s++;
m=a[i];
if(s>max)
{
t=m;
max=s;
}
}
printf("%d\n%d\n",t,max);
return?
0;
}
5、算法分析:
主函数内调用的库函数sort(a,a+n)的时间复杂度为,for循环的时间杂度为Ο(n),故该算法的时间杂度为。
实验四半数集问题
1、问题描述:
?
给定一个自然数n,由n开始可以依次产生半数集set(n)中的数如下:
(1)n∈set(n);
(2)在n的左边加上一个自然数,但该自然数不能超过最近添加的数的一半;(3)按此规则进行处理,直到不能再添加自然数为止。
例如:
set(6)={6,16,26,126,36,136},半数集set(6)中有6个元素。
注意半数集
是多重集,对于给定的自然数n,编程计算半数集set(n)中的元素个数。
2、题目分析:
题目要求输入有多行,每行给出一个整数n(0半数集set(n)中的元素个数即为所有半数集set(j)(j<=n/2)的元素个数之和加1(即将其自身添加到所求元素中)。
3、算法设计:
a.用数组count[i]计算set(i)中的元素个数,即计算所有j<=i/2的set(j)中的元素加
其自身的个数之和;
b.用数组count_sum[i]计算所有j<=i的set(j)中的元素个数之和;
c.采用for循环分别对count[i]、count_sum[i]进行累加,即可求出半数集set(n)中的
元素个数。
4、源程序:
#include
intset(intn)
{
inti,count[1001],count_sum[1001];
count[1]=1;
count_sum[1]=1;
for(i=2;i<=n;i++)
{
count[i]=count_sum[i/2]+1;
count_sum[i]=count_sum[i-1]+count[i];
}
returncount[n];
}
main()
{
intn;
while(scanf("%d",&n)!
=EOF)
printf("%d\n",set(n));
return0;
}
5、算法分析:
函数set(n)的时间复杂度为Ο(n),主函数调用函数set(n),故该算法的时间复杂度为Ο(n)。
实验五集合划分问题
2、题目分析:
题目要求计算n个元素的集合共有多少个划分(其中每个划分都由不同的非空子集组成),n个元素的集合划分为m个块的划分数为F(n,m)=F(n-1,m-1)+m*F(n-1,m),m从1到n的划分个数相加即可求得总的划分数。
3、算法设计:
a.这一题的结果数很大,需要使用64位长整型:
__int64;
b.函数div()采用递归的方式计算n个元素的集合划分为i个块的划分数:
①div(n,1)=1,div(n,n)=1;
②div(n,i)=div(n-1,i-1)+i*div(n-1,i)
c.主函数采用for循环调用函数div(n,i)(1≤i≤n)对划分数进行累加统计。
4、源程序:
#include
__int64?
div(__int64?
n,__int64?
i)
{
if(i==1||i==n)
return?
1;
else?
return?
div(n-1,i-1)+i*div(n-1,i);
}
main()
{
__int64?
i,n,s=0;
scanf("%I64d",&n);
for(i=1;i<=n;i++)
s=s+div(n,i);
printf("%I64d",s);
return?
0;
}
5、算法分析:
函数div()的时间复杂度为,主函数内for循环的时间复杂度为O(n),函数div()嵌套在for循环内,故该算法的时间复杂度为。
实验七编辑距离问题
1、问题描述:
?
设A和B是2个字符串。
要用最少的字符操作将字符串A转换为字符串B。
这
里所说的字符操作包括
(1)删除一个字符;
(2)插入一个字符;(3)将一个字符改为另
一个字符。
将字符串A变换为字符串B所用的最少字符操作数称为字符串A到B的编
辑距离,记为d(A,B)。
试设计一个有效算法,对任给的2个字符串A和B,计算出它
们的编辑距离d(A,B)。
2、题目分析:
题目要求计算两字符串的编辑距离,可以采用动态规划算法求解,由最优子结构性质可建立递归关系如下:
其中数组d[i][j]存储长度分别为i、j的两字符串的编辑距离;用edit标记所比较
的字符是否相同,相同为0,不同为1;用m、n存储字符串a、b的长度。
3、算法设计:
a.函数min()找出三个数中的最小值;
b.函数d()计算两字符串的编辑距离:
①用edit标记所比较的字符是否相同,相同为0,不同为1;
②分别用m、n存储字符串a、b的长度,用数组d[i][j]存储长度分别为i、j的两字符串的编辑距离,问题的最优值记录于d[n][m]中;
③利用递归式写出计算d[i][j]的递归算法。
4、源程序:
#include
usingnamespacestd;
intmin(inta,intb,intc)
{
inttemp=(a
a:
b);
return(temptemp:
c);
}
intd(char*a,char*b)
{
intm=strlen(a);
intn=strlen(b);
inti,j,temp;
int**d;
d=(int**)malloc(sizeof(int*)*(m+1));
for(i=0;i<=m;i++)
{
d[i]=(int*)malloc(sizeof(int)*(n+1));
}
d[0][0]=0;
for(i=1;i<=m;i++)
d[i][0]=i;
for(j=1;j<=n;j++)
d[0][j]=j;
for(i=1;i<=m;i++)
{
for(j=1;j<=n;j++)
{
intedit=(a[i-1]==b[j-1]?
0:
1);
d[i][j]=min((d[i-1][j-1]+edit),
(d[i][j-1]+1),(d[i-1][j]+1));
}
}
temp=d[m][n];
free(d);
returntemp;
}
main()
{
chara[10000],b[10000];
scanf("%s\n%s",a,b);
printf("%d",d(a,b));
return0;
}
5、算法分析:
函数d()采用了双重循环,里层的for循环复杂度为O(n),外层的for循环复杂度为O(m),主函数调用了函数d(),故该算法的时间复杂度为O(mn)。
实验八程序存储问题
1、问题描述:
设有n个程序{1,2,…,n}要存放在长度为L的磁带上。
程序i存放在磁带上的长度是il,1≤i≤n。
程序存储问题要求确定这n个程序在磁带上的一个存储方案,使得能够在磁带上存储尽可能多的程序。
对于给定的n个程序存放在磁带上的长度,编程计算磁带上最多可以存储的程序数。
2、题目分析:
题目要求计算给定长度的磁带最多可存储的程序个数,先对程序的长度从小到大排序,再采用贪心算法求解。
3、算法设计:
a.定义数组a[n]存储n个程序的长度,s为磁带的长度;
b.调用库函数sort(a,a+n)对程序的长度从小到大排序;
c.函数most()计算磁带最多可存储的程序数,采用while循环依次对排序后的程序
长度进行累加,用i计算程序个数,用sum计算程序累加长度(初始i=0,sum=0):
①sum=sum+a[i];
②若sum<=s,i加1,否则i为所求;
③i=n时循环结束;
d.若while循环结束时仍有sum<=s,则n为所求。
4、源程序:
#include
usingnamespacestd;
#include
inta[1000000];
intmost(int*a,intn,ints)
{
inti=0,sum=0;
while(i{
sum=a[i]+sum;
if(sum<=s)
i++;
elsereturni;
}
returnn;
}
main()
{
inti,n,s;
scanf("%d%d\n",&n,&s);
for(i=0;iscanf("%d",&a[i]);
sort(a,a+n);
printf("%d",most(a,n,s));
return0;
}
5、算法分析:
函数most()的时间杂度为Ο(n),主函数调用的库函数sort(a,a+n)的时间复杂度为,且主函数调用函数most(),故该算法的时间杂度为。
实验九最优服务次序问题
1、问题描述:
设有n个顾客同时等待一项服务。
顾客i需要的服务时间为ti,1≤i≤n。
应如何安排n个顾客的服务次序才能使平均等待时间达到最小?
平均等待时间是n个顾客等待服务时间的总和除以n。
对于给定的n个顾客需要的服务时间,编程计算最优服务次序。
2、题目分析:
考虑到每个顾客需要的服务时间已给定,要计算最优服务次序,可以先对顾客需要的服务时间由短到长排序,再采用贪心算法求解。
3、算法设计:
a.定义数组a[n]存储n个顾客需要的服务时间;
b.调用库函数sort(a,a+n)对顾客需要的服务时间由短到长排序;
c.函数time()计算最小平均等待时间,采用while循环依次对顾客等待服务时间进
行累加,用a[i]标记第i+1个顾客需要的服务时间,用b[i]计算第i+1个顾客的等待服务
时间,用t计算前i+1个顾客等待服务时间的总和(初始i=1,t=a[0],b[0]=a[0]):
①b[i]=a[i]+b[i-1],t=b[i]+t;
②i++;
③i=n时循环结束;
d.t/n为所求。
4、源程序:
#include
usingnamespacestd;
#include
inta[1000000],b[1000000];
doubletime(int*a,intn)
{
inti=1,j=0;
doublet=a[0];
b[0]=a[0];
while(i{
b[i]=a[i]+b[i-1];
t=b[i]+t;
i++;
}
returnt/n;
}
main()
{
inti,n;
scanf("%d",&n);
for(i=0;iscanf("%d",&a[i]);
sort(a,a+n);
printf("%0.2lf",time(a,n));
return0;
}
5、算法分析:
函数time()的时间杂度为Ο(n),主函数调用的库函数sort(a,a+n)的时间复杂度为,且主函数调用函数time(),故该算法的时间杂度为。
实验十汽车加油问题
1、问题描述:
?
一辆汽车加满油后可行驶n公里。
旅途中有若干个加油站。
设计一个有效算法,指出应在哪些加油站停靠加油,使沿途加油次数最少。
并证明算法能产生一个最优解。
对于给定的n和k个加油站位置,编程计算最少加油次数。
2、题目分析:
题目要求编程计算最少加油次数,若无法到达目的地,则输出“NoSolution”。
该题可以采用贪心算法求解,从出发地开始进行判别:
油足够则继续行驶;油不够则加油,计算加油次数;油满仍不够则“NoSolution”。
3、算法设计:
a.n表示汽车加满油后可行驶n公里,k表示出发地与目的地之间有k个加油站;
b.定义数组a[k+1]存储加油站之间的距离:
用a[i]标记第i个加油站与第i+1个加
油站之间的距离(第0个加油站为出发地,汽车已加满油;第k+1个加油站为目的地);
c.用m计算加油次数,用t标记在未加油的情况下汽车还能行驶t公里,采用for
循环从出发地开始(即i=0)依次计算加油次数:
①若a[i]>n,则输出“NoSolution”;
②若tt=n,m++;
③行驶a[i]公里后,汽车还能行驶t-a[i]公里;
④i=k+1时循环结束;
d.m即为所求。
4、源程序:
#include
main()
{
inti,n,k,t,m,a[10000];
scanf("%d%d",&n,&k);
for(i=0;i<=k;i++)
scanf("%d",&a[i]);
m=0;
t=n;
for(i=0;i<=k;i++)
{
if(a[i]>n)
{
printf("NoSolution");
break;
}
elseif(t{
t=n;m++;
}
t=t-a[i];
}
if(i==k+1)
printf("%d",m);
return0;
}
5、算法分析:
主函数内for循环的时间复杂度为O(k),故该算法的时间杂度为O(k)。
实验十一工作分配问题
1、问题描述:
?
?
设有n件工作分配给n个人。
将工