算法设计与分析课后习题.docx
《算法设计与分析课后习题.docx》由会员分享,可在线阅读,更多相关《算法设计与分析课后习题.docx(19页珍藏版)》请在冰豆网上搜索。
算法设计与分析课后习题
1、实验内容递归
求n的二次方各项的系数。
2、程序设计
代码如下:
#include"stdio.h"
voidcoeff(inta[],intn)
{
if(n==1)
{
a[1]=1;a[2]=1;
}
else
{
coeff(a,n-1);
a[n+1]=1;
for(inti=n;i>=2;i=i-1)
a[i]=a[i]+a[i-1];
a[1]=1;
}
}
voidmain()
{
inta[100],i,n;
printf("输入n的值:
");
scanf("%d",&n);
coeff(a,n);
for(i=1;i<=n+1;i++)
printf("%d",a[i]);
printf("\n");
}
3、运行结果
1、实验内容
写出计算ackerman函数ack(m,n)的递归计算函数。
2、程序设计
代码如下:
#include"stdio.h"
intack(intm,intn)
{
if(m==0)
returnn+1;
elseif(n==0)
returnack(m-1,1);
else
returnack(m-1,ack(m,m-1));
}
voidmain()
{
intm,n,z;
printf("inputmandn:
");
scanf("%d%d",&m,&n);
if(m<0&&n<0)
printf("errorinput!
");
else
z=ack(m,n);
printf("%d\n",z);
}
3、运行结果
第四章
例15求数列的最大子段和
给定n个元素的整数列(可能为负整数)a1,a2,…..,an。
求形如:
ai,ai+1,……aji,j=1,…..,n,i<=j
的子段,使其和为最大。
当所有整数均为负整数时定义其最大子段和为0.
程序:
#include
intmaxsum2(inta[],intleft,intright)
{
intcenter,i,left_sum,right_sum,s1,s2,lefts,rights;
if(left==right)
if(a[left]>0)
returna[left];
else
return0;
else
{
center=(left+right)/2;
left_sum=maxsum2(a,left,center);
right_sum=maxsum2(a,center+1,right);
s1=0;
lefts=0;
for(i=center;i>=left;i--)
{
lefts=lefts+a[i];
if(lefts>s1)
s1=lefts;
}
s2=0;
rights=0;
for(i=center+1;i<=right;i++)
{
rights=rights+a[i];
if(rights>s2)
s2=rights;
}
if((s1+s2returnleft_sum;
if(s1+s2returnright_sum;
return(s1+s2);
}
}
intmaxsum1(inta[],intn)
{
return(maxsum2(a,1,n));
}
voidmain()
{
inta[100],n;
printf("enteranumber:
");
scanf("%d",&n);
printf("enterthenumberofa[]:
");
for(inti=1;i<=n;i++)
scanf("%d",&a[i]);
printf("%d",maxsum1(a,n));
printf("\n");
}
运行结果:
回溯法
N皇后问题
例如:
8皇后问题:
要在8×8的国际象棋棋盘中放8个皇后,使任意两个皇后都不能互相吃掉。
规则是皇后能吃掉同一行、同一列、同一对角线的任意棋子。
下图为一种方案,求所有的解。
0
0
0
0
0
0
0
0
模型建立:
不妨设8个皇后为xi,他们分别在第i行(i=1,2,3,4,5,6,7,8),这个问题的解空间,就是一个8个皇后所在的序号,为n元一维向量(x1,x2,x3,x4,x5,x6,x7,x8),搜索空间是1<=xi<=8(i=1,2,3,4,5,6,7,8),共88个状态。
约束条件是8个点(1,x1),(2,x2),(3,x3),(4,x4),(5,x5),(6,x6),(7,x7),(8,x8)不在同一列和同一对角线上。
算法设计:
用回溯法从开始结点出发,以深度优先的方式搜索整个解空间。
这个开始结点就成为一个活结点,同时也成为当前的扩展结点。
在当前的扩展结点出,搜索向纵深方向移动至一个活结点。
这个新结点就成为一个新的活结点,并成为当前扩展结点。
如果在当前的扩展结点出不能再向纵深方向移动,则当前扩展结点就成为死结点。
此时,应往回移动(回溯)至最近的一个活结点处,病史这个活结点成为当前的扩展结点。
回溯法即以这种工作方式递归的在解空间中搜索,直至找到所要求的解或解空间中已没有活结点时为止。
程序设计:
#include
#include
voidbackdate(intn);
intcheck(intk);
inta[20],n;
voidmain()
{
printf("PleaseinputanumberN>3:
\n");
scanf("%d",&n);
backdate(n);
}
voidbackdate(intn)
{
intk;
a[1]=0;
k=1;
while(k>0)
{
a[k]=a[k]+1;
while((a[k]<=n)&&(check(k)==0))
a[k]=a[k]+1;
if(a[k]<=n)
if(k==n)
{inti;
printf("%d皇后的解为:
\n",n);
for(i=1;i<=n;i++)
printf("%d\n",a[i]);
}
else
{
k++;
a[k]=0;
}
else
k--;
}
}
intcheck(intk)
{
inti;
for(i=1;i<=k-1;i++)
if((abs(a[i]-a[k])==abs(i-k))||(a[i]==a[k]))
return(0);
return
(1);
}
运行结果:
例12狱吏问题
算法1
程序:
#include
#include
voidmain()
{
int*a,i,j,n;
scanf("%d",&n);
a=(int*)calloc(n+1,sizeof(int));
for(i=1;i<=n;i++)
a[i]=1;
for(i=1;i<=n;i++)
for(j=i;j<=n;j=j+i)
a[j]=1-a[j];
for(i=1;i<=n;i++)
if(a[i]==0)
{
printf("%disfree.",i);
printf("\n");
}
}
运行结果:
算法2
程序:
#include
voidmain()
{
ints,i,j,n;
scanf("%d",&n);
for(i=1;i<=n;i++)
{
s=1;
for(j=2;j<=i;j++)
if(i%j==0)
s=s+1;
if(s%2==1)
{
printf("%disfree.",i);
printf("\n");
}
}
}
运行结果:
算法3
程序:
#include
voidmain()
{
inti,n;
scanf("%d",&n);
for(i=1;i<=n;i++)
if(i*i<=n)
{
printf("%disfree.",i*i);
printf("\n");
}
else
break;
}
运行结果:
贪婪法
例4.22货币统计问题
某单位给每个职工发工资(精确到元)。
为了保证不要临时兑换零钱,且取款的张数最少,取工资前要统计出所有职工的工资所需各种币值(100,50,20,10,5,2,1共7种)的张数,请编程完成。
源程序如下:
#include"stdio.h"
voidmain(){
inti,j,n,GZ,A,B[8]={0,100,50,20,10,5,2,1},S[8]={0,0,0,0,0,0,0,0};
printf("请输入人数:
");
scanf("%d",&n);
for(i=1;i<=n;i=i+1){
printf("输入工资:
");
scanf("%d",&GZ);
for(j=1;j<=7;j=j+1){
A=GZ/B[j];
S[j]=S[j]+A;
GZ=GZ-A*B[j];
}
}
for(i=1;i<=7;i=i+1)
printf("币值%5d,张数%5d\n",B[i],S[i]);
}
运行结果:
习题4.3
问题描述:
54张扑克牌,两人轮流拿,每人每次最少拿一张,最多纳四张,谁拿最后一张谁输。
编写模拟计算机先拿牌且必胜的算法。
原代码如下:
#include
main()
{
inti,a[10];
printf("甲4\n");
for(i=0;i<10;i++)
{
scanf("%d",&a[i]);
if(a[i]>=1&&a[i]<=4)
{
printf("\n乙%d\t甲%d\n",a[i],5-a[i]);
}
else
{
printf("\n你输入的数据有误\n");
return0;
}
}
printf("甲胜\n");
}
运行结果:
资源分配
#include
voidmain()
{
inti,j,k,m,n,rest;
inta[100][100],gain[100];
floatq[100],f[100],temp[100];
printf("Howmanyitem?
");scanf("%d",&m);
printf("Howmuchmoney?
");scanf("%d",&n);
printf("inputgaintable:
");
for(j=0;j<=n;j++)
{
scanf("%f",&q[j]);
f[j]=q[j];
}
for(j=0;j<=n;j++)
a[1][j]=j;
for(k=2;k<=m;k++)
{
printf("inputanotheritemgaintable\n");
for(j=0;j<=n;j++)
{
temp[j]=q[j];
scanf("%f",&q[j]);
a[k][j]=0;
}
for(j=0;j<=n;j++)
for(i=0;i<=j;i++)
if(f[j-i]+q[i]>temp[j])
{
temp[j]=f[j-i]+q[i];
a[k][j]=i;
}
for(j=0;j<=n;j++)
f[j]=temp[j];
}
rest=n;
for(i=m;i>=1;i--)
{
gain[i]=a[i][rest];
rest=rest-gain[i];
}
for(i=1;i<=m;i++)
printf("第%d个项目分配资源%d\n",i,gain[i]);
printf("最大利润为%f\n",f[n]);
}