算法与分析平时作业答案.docx

上传人:b****7 文档编号:8971581 上传时间:2023-02-02 格式:DOCX 页数:14 大小:22.53KB
下载 相关 举报
算法与分析平时作业答案.docx_第1页
第1页 / 共14页
算法与分析平时作业答案.docx_第2页
第2页 / 共14页
算法与分析平时作业答案.docx_第3页
第3页 / 共14页
算法与分析平时作业答案.docx_第4页
第4页 / 共14页
算法与分析平时作业答案.docx_第5页
第5页 / 共14页
点击查看更多>>
下载资源
资源描述

算法与分析平时作业答案.docx

《算法与分析平时作业答案.docx》由会员分享,可在线阅读,更多相关《算法与分析平时作业答案.docx(14页珍藏版)》请在冰豆网上搜索。

算法与分析平时作业答案.docx

算法与分析平时作业答案

平时作业

1、给定下述二分搜索算法,请判断算法的正确性,指出错误算法的产生原因。

a)intBinarySearch(Typea[],constType&x,intl,intr){while(r>=l){

intm=(l+r)/2;

if(x==a[m])returnm;

if(x

elsel=m+1;

}

return-1;

}

答:

正确

b)intBinarySearch(Typea[],constType&x,intl,intr){

while(r>=l){

intm=(l+r)/2;

if(x==a[m])returnm;

if(x

elsel=m-1;

}

return-1;

}

答:

错误

if(x

,修改成if(x

c)intBinarySearch(Typea[],constType&x,intl,intr){

while(r>l){intm=(l+r)/2;

if(x==a[m])returnm;

if(x

elsel=m+1;

}

return-1;

}

答:

错误。

while(r>l)要考虑到数组只有一个元素的情况所以应该是r>=l;

2、0

(1)空间子数组环卫算法:

设a[0:

n-1]是一个n维数组,k(Kk

整数。

试设计一个算法将子数组a[0:

k-1]与a[k+1:

n-1]换位。

要求算法在最坏情况下耗时0(n),且只用0

(1)的辅助空间。

答:

最简单的方法就是循环(n-k-1)次,将a数组的末尾数字插入到a[0]之前。

具体做法:

(1)首先开辟一个额外空间temp用于存放每一次a数组的末尾数据。

(2)temp<-a[n-1]

(3)将a[0:

n-2]每个数据都依次向后移动一位赋值给a[1:

n-1]。

(4)a[0]<-temp

(5)循环执行

(2)-(4)步(n-k+1)次。

代价分析:

时间代价0((n-1)*(n-k+1))即0(nA2)数量级;空间代价:

0

(1)

3、定义:

给定一个自然数n,由n开始依次产生半数集set(n)中的元素如下:

1)nset(n);

2)在n的左边加上一个自然数,但该自然数不能超过最近添加的数的一半;

3)按此规则进行处理,直至不能再添加新的自然数为止。

例如set(n){6,16,26,126,36,136}。

其中共有6个元素。

半数集问题:

对于给定的n,求半数集set(n)中元素的个数。

答:

半数集set(n)中元素个数的求解是个递归的过程。

设set(n)中的元素个数为f(n),则显然有递归表达式:

f(n)=1+刀f(i),i=1,2n/2。

即半数集set(n)元素个数

f(n)=1+f

(1)+f

(2)+...+f(floor(n/2)).用递推法求解。

C语言代码如下:

#include#include

intmain(){

intn;

inti,j,s;

intbuf[106];

char*in="input.txt",*out="output.txt";

FILE*ip,*op;

if((ip=fopen(in,"r"))==NULL)return1;if((op=fopen(out,"w"))==NULL)return2;

fscanf(ip,"%d",&n);

fclose(ip);

buf[1]=1;

buf[2]=2;

buf[3]=2;

for(i=4;i*2<=n;i++){

s=1;

for(j=1;j<=i/2;j++){

s+=buf[j];

}

buf[i]=s;

}

s=1;

for(j=1;j<=n/2;j++){

s+=buf[j];

}

fprintf(op,"%d",s);

fclose(op);

/*system("pause");*/

return0;

}

4、设计一个算法,找出由n个数组成的序列的最长单调递增子序列的长度。

答:

#include#definem10

//快速排序

voidQuickSort(intR[],ints,intt){

inti=s,j=t;inttmp;

if(s

tmp=R[s];

while(i!

=j){while(j>i&&R[j]>=tmp)j--;R[i]=R[j];while(i

}

R[i]=tmp;

QuickSort(R,s,i-1);

QuickSort(R,i+1,t);

}

//找出最长公共子序列

voidLCSLength(intx[],inty[],intn,intc[m][m],intb[m][m]){

inti,j;for(i=0;i

c[0][i]=0;c[i][0]=0;

}

for(i=0;i

if(x[i]==y[j]){

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

}elseif(c[i-1][j]>=c[i][j-1]){

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

b[i][j]=2;

}else{

c[i][j]=c[i][j-1];b[i][j]=3;

}

}

}

voidLCS(inti,intj,int*x,intb[m][m]){

if(i<0||j<0)return;if(b[i][j]==1){

LCS(i-1,j-1,x,b);cout<

}elseif(b[i][j]==2)LCS(i-1,j,x,b);

elseLCS(i,j-1,x,b);

}

voidmain(){

intx[m],y[m],d;

cout<<"请输入元素个数"<>d;

cout<<"请输入元素"<

for(inti=0;i

cin>>x[i];y[i]=x[i];

}

intc[m][m]={0},b[m][m]={0};

QuickSort(x,0,d-1);

LCSLength(x,y,d,c,b);

cout<<"最长单调递增子序列为:

"<

}

5、会场安排问题:

假设要在足够多的会场里安排一批活动,并希望使用尽可能少的会场。

设计一个有效的贪心算法进行安排。

对于给定的n个待安排的活动,计算使用最少会场的个数。

每个活动i都有一个开始时间和结束时间,分别表示为b(i),f(i)。

答:

#include

usingnamespacestd;#defineM50//最大活动数structActive{

intb;//开始时间

intf;//结束时间

intno;//预安排会场号

}a[M];

//两元素交换位置

voidswap(Active&a,Active&b){

Activet=a;a=b;b=t;

}

voidmain(){intk,i,j;cout<<"输入待安排活动数:

"<>k;cout<<"输入待安排活动的开始时间和结束时间:

"<

{for(j=i;j<=k;j++){if(a[i].b>a[j].b)swap(a[i],a[j]);if(a[i].b==a[j].b){if(a[i].f>a[j].f)swap(a[i],a[j]);

}

}

}

intintsum=1;//使用的会场数初始化

intn;a[1].no=sum;for(i=2;i<=k;i++){for(n=1;n

=0&&a[n].f<=a[i].b){a[i].no=a[n].no;a[n].no=0;//已经安排过的活动就不再比较break;}

}

if(n==i)

{

sum+=1;a[i].no=sum;

}}cout<<"输出最少会场数:

\n"<

}

6、最优分解问题:

设n是一个正整数。

现要求将n分解为若干个互不相同的自然数的和,使得这些自然数的乘积最大。

设计一个算法,得到最优分解方案。

分析:

我们知道如果a+b=常数,贝U|a-b|越小,a*b越大。

贪心策略:

将n分成从2开始的连续自然数的和。

如果最后剩下一个数,将此数在后项优先的方式下均匀地分给前面各项。

答:

voiddicomp(intn,int[]a)

{

intk=1;

if(n<3){a[1]=0;return;}

if(n<5){a[k]=1;a[++k]=n-1;return;}

a[1]=2;

n-=2;

while(n>a[k]){

k++;

a[k]=a[k-1]+1;

n-=a[k];

}

if(n==a[k]){

a[k]++;n--;

}

for(inti=0;i

}

7、子集和问题:

设S{Xi,X2丄,Xn}是n个正整数的集合,c是一个正整数。

那么是否存在S的一个子集S,使得子集中元素之和等于c,即xC。

XS1

答:

#include

intn,c;inta[100];

intcurrent[100];//存放当前选择的情况

intbest[100];//存放最后选择的子集合,best[i]=1,表示包含,反之即不包含。

intd=1;//判断有无满足的情况

intd2=0;//是否已经选出子集和

voidBack(intm,intcount);

intmain(){

inti,j;

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

for(i=0;i

}

Back(0,0);

if(d)printf("nosolution\n");for(j=0;j

{

if(best[j]==1)printf("%d\t\t",a[j]);

}

voidBack(intm,intcount){

intk;if(m>n)return;if(count==c){d=0;//有满足的子集和if(d2)return0;for(k=0;k<=m;k++)best[k]=current[k];d2=1;return0;

}else{

current[m]=1;//选入子集和count+=a[m];

Back(m+1,count);

current[m]=0;//不选入子集和count=count-a[m];Back(m+1,count);

}

}

8设序列Z{Zi,Z2丄,Zk}是序列X{Xi,X2丄,Xm}和丫{%」2丄,yn}的最长公共子序列。

a)请说明最长公共子序列具有最优子结构性质。

b)设C[i][j]记录序列Xi{X1,X2,L,Xi}和Yj{yi,y2,L,yj}的最长公共子序列的长

i度。

由最长公共子序列问题的最优子结构性质建立子问题最优值C[i][j]的递归关系。

C)写出寻找最长公共子序列的算法。

答:

最长公共子序列问题具有最优子结构性质:

Ji门.

1、若Xm=yn,

则Zk=Xm=yn

,且Z[k-1]是X[m-1]和Y[n-1]的最长公共子序列

2、若Xm!

=yn

,且Zk!

=Xm,

则Z是X[m-1]和Y的最长公共子序列

3、若Xm!

=yn,

且Zk!

=yn,

则Z是Y[n-1]和X的最长公共子序列由性质导出子

问题的递归结构:

当i=0,j=0

时,c[i][j]=0

当i,j>0Xi=yi

时,c[i][j]=

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

当i,j>0Xi!

=yi

时,c[i][j]

=maX{c[i][j-1],c[i-1][j]}

publicclassLSC{

privateint[][]c,b;

privateintm,n;

privatechar[]A,B;

publicLSC(char[]A,char[]B){

this.A=A;

this.B=B;

m=A.length;

n=B.length;

c=newint[m+1][n+1];b=newint[m+1][n+1];

for(inti=0;i

c[0][i]=0;

}for(intj=0;j

}

}

publicLSC(){}

publicintLSCLength(){for(inti=1;i

是相等的话*/

for(intj=1;j

**如果A[i-1]和E[j-1]if(A[i-1]==B[j-1]){c[i][j]=c[i-1][j-1]+1;b[i][j]='0';

}

/**情况1*/

elseif(c[i-1][j]>=c[i][j-1]){c[i][j]=c[i-1][j];b[i][j]='1';

}

/**情况2*/

else{c[i][j]=c[i][j-1];b[i][j]='2';

}

}

}

returnc[m][n];

}

publicvoidprint(inti,intj){if(i<=0||j<=0){return;}elseif(b[i][j]=='0'){

print(i-1,j-1);System.out.print(A[i-1]);

}elseif(b[i][j]=='1'){print(i-1,j);

}else{print(i,j-1);

publicintLSCLength2(inti,intj){if(i<0||j<0){return0;}else{

if(A[i]==B[j]){

return1+LSCLength2(i-1,j-1);

}

else{

inta1=LSCLength2(i,j-1);

inta2=LSCLength2(i-1,j);returna1>a2?

a1:

a2;

}

}

}

publicstaticvoidmain(String[]args){

char[]A={'g','f','d','a','s','d','a','c'};

char[]B={'g','c','f','a','t','0','c','c'};LSClsc=newLSC(A,B);System.out.println(lsc.LSCLength2(7,7));

}

}

9、记矩阵连乘积A[i,j]%AiAi1...Aj,ij。

确定计算A[1:

n]的最优计算次序,使得所

需数乘的次数最少。

1、说明矩阵连乘计算次序问题的最优解包含着其子问题的最优解,即最优子结构性质。

2、该问题具备子问题的重叠性质。

3、说明采用动态规划方法可以解决该问题。

4、设计该算法,分析算法的复杂性。

答:

计算A[i:

j]的最优次序所包含的计算矩阵子链A[i:

k]和A[k+1:

j]的次序也是最优的。

设计算A[i:

j],wiwjwn,所需要的最少数乘次数m[i,j],则原问题的最优值为m[1,n]

当i=j时,A[i:

j]=Ai,无需计算,因此,m[i,j]=O,i=1,2,…,n

当i

j]的最优次序在Ak和Ak+1之间断开,则

m:

i,j]=m:

i,k:

+m“+1,门+pi-ipkpj

其中Ai的维数为pi-1xpjk的位置只有j-i种可能,{i,i+1,…,j-1},其中使计算

量最小的那个位置为最优解,数乘次数m[i,j]最小值为问题的最优值可以递归地定义m[i,j]为:

{0i=j}

m[i,j]={min{m[i,k]+m[k+1,j]+pi-1pkpj}i

将最优值m[ij]对应的断开位置记为s[ij],则可递归的由s[ij]构造出相应的最优解对于1wiwjwn不同的有序对(i,j)对应于不同的子问题。

因此,不同子问题的个数最多只有

由此可见,在递归计算时,许多子问题被重复计算多次。

这也是该问题可用动态规划算法求解的又一显著特征。

用动态规划算法解此问题,可依据其递归式以

自底向上的方式进行计算。

在计算过程中,保存已解决的子问题答案。

每个子

问题只计算一次,而在后面需要时只要简单查一下,从而避免大量的重复计算

最终得到多项式时间的算法matrixchain已经记录了构造最优解所需的全部信

息。

从s[1][n]可知,计算A[1:

n]的最优加括号方式为(A[1:

s[1][n]])

(A[s[1][n]+1:

n])计算A[1:

s[1][n]]的最优加括号方式为(A[1:

s[1][s[1][n]]])(A[s[1][s[1][n]]+1:

s[1][n]])

10、考虑分数背包问题,定义如下:

给出n个大小为si,s2,…,sn,价值为vi,v2,…,

n

Vn的物品,并设背包容量为C,要找到非负实数X1,X2,…,Xn,使和XiVi在约束

ni1

XisiC下最大。

写出求解问题的贪心算法,估计算法的时间复杂性。

i1

答:

从问题的某一初始解出发;while能朝给定总目标前进一步do求出可行解的一个解元素;由所有解元素组合成问题的一个可行解;从问题的某一个初始解出发逐步逼近给定的目标,以尽可能快的地求得更好的解。

当达到某算法中的某一步不能再继续前进时,算法停止。

#inelude#definetotal

10floatp[total],w[total],t[total];voidgreedy_knaPsack(intX,intc)

{intnote,i;floatmax;while

(1){note=0;max=0;for(i=0;i

{t[note]=1;c-=w[note];}else{t[note]=c/w[note];break;}}}intmain()

{inti=0,n=0;floatcu;printf("请输入物品总数(不大于%d与背包的容

量:

",total);while

(1)

{scanf("%d%f",&n,&cu);if(n

围,请重新输入:

");}printf("请输入每个物品的价值与重量:

\n");for(i=0;i

\n");for(i=0;i

算法

中用到三个for循环,故计算时间复杂度:

O(n)=n+n+n=3n即此算法的时间复杂度为:

O(n)=n

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 工程科技 > 电力水利

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1