算法设计与应用作业.docx
《算法设计与应用作业.docx》由会员分享,可在线阅读,更多相关《算法设计与应用作业.docx(11页珍藏版)》请在冰豆网上搜索。
算法设计与应用作业
1有52张牌,使它们全部正面朝上,第一轮是从第2张开始,凡是2的倍数位置上的牌翻成正面朝下;第二轮从第3张牌开始,凡是3的倍数位置上的牌,正面朝上的翻成正面朝下的,正面朝下的翻成正面朝上的;以此类推,直到翻得牌超过104张为止。
统计最后有几张牌正面朝上以及它们的位置号。
问题分析:
52张牌都有一个初始状态,即全部朝上。
第一轮开始时,2的倍数位置改变,非2的倍数保持原样;第二轮开始时,3的奇数倍朝下,3的偶数倍朝上;第三轮开始时,4的倍数朝上,即2的偶数倍朝下,以此类推,直到牌数超过104,则进行状态统计。
算法设计:
根据题意,首先对第一轮进行记录,算法则应该是依次对位置进行改变,用循环求解翻转问题。
算法分析:
这个算法使用循环对牌进行逐层比较,算法复杂度为O(n+1),使用了52个空间的一维数组。
数据结构设计:
用一维数组a[52]表示52张牌,设其初始状态为0。
计数小于104时,第一轮开始进行翻转,下一轮即n+1轮开始分情况进行翻转,用整型shang进行朝上个数的统计,位置则由i来确定。
算法如下:
#include
intmain()
{
inta[52]={0};//用一维数组表示52张牌,0表示正面朝上
intshang=0;//正面朝上的个数
inti=0;
intcount=0;//次数统计
intn=1;
while(count<=104)
{
if(n==1)
{
for(i=n+1;i<=52;++i)
{
if(i%(n+1)==0)
{
a[i-1]=1;
//front--;
++count;
}
}
n++;
}
else
{
for(i=n+1;i<=52;++i)
{
if(i%(n+1)==0)
{
if(a[i-1]==0)
{a[i]=1;
++count;
}
else
{
a[i]=0;
++count;
}
}
}
n++;
}
}
for(i=0;i<52;++i)
{
if(a[i]==0)
{
shang++;
}
}
printf("正面朝上的扑克有:
%d\n",shang);
printf("它们的位置号为:
\n");
for(i=0;i<52;++i)
{
if(a[i]==0)
{
printf("%d\t",i);
}
}
printf("\n");
return0;
}
运行结果如下:
1.键盘输入n个正整数,把它们看作一个“数圈”,求其中连续4个数之和最大者。
问题分析:
用数1到n表示键盘输入的数,把连续4个数之和同前后进行比较,求出和最大,可利用二重循环把所有情况进行列举。
算法设计:
用1,2,3…n代表输入的数,其存储的值代表连续4个数之和。
第一层循环:
范围从n到n+4;
第二层循环:
范围从1到n;
最后对和进行比较,然后输出。
算法分析:
算法效率为O(4n),存储空间上有些浪费,可根据实际情况进行空间分配。
数据结构设计:
首先用一个一维数组表示键盘输入的数,定义一个最大数,设置其初始状态为0,把连续4个数的和用he表示,再同max进行比较,输出内容就是问题的解。
算法如下:
#include
intmain(void)
{intch[120],n,i,j,he=0,max=0,maxi;
scanf("%d",&n);
for(i=0;iscanf("%d",&ch[i]);
for(i=n;ich[i]=ch[i-n];
for(i=0;i{he=ch[i]+ch[i+1]+ch[i+2]+ch[i+3];
if(he>max)
{
max=he;maxi=i;}
}
i=maxi;
printf("最大和=%d+%d+%d+%d=%d\n",
ch[i],ch[(i+1)%n],ch[(i+2)%n],ch[(i+3)%n],he);
return0;
}
运行结果如下:
2.有一堆棋子,2枚2枚地数,最后余1枚;3枚3枚地数,最后余2枚;5枚5枚地数,最后余4枚;6枚6枚地数,最后余5枚;7枚7枚地数,最后正好数完,编程完成这堆棋子最少有多少枚棋子。
问题分析:
用n表示棋子数,要求可以7枚7枚的数,因此棋子数至少为7,问题可以用条件语句进行求解。
算法设计:
用7到n表示棋子数,余数表示剩余的棋子数。
设置棋子数的范围,因为不知道具体有多少,所以尽可能的大一点,然后进行情况判别。
算法分析:
算法比较简单,但由于预先不知道棋子数,因此效率比较差。
数据结构分析:
首先预确定一个棋子数的范围,分别对2、3、5、7进行取余,符合情况则输出棋子数n,不符合则加1,继续进行判断,输出结构符合问题要求。
算法如下:
#include
intmain(void)
{
intn=7;
while(n<1000)
{
if(n%2==1&&n%3==2&&n%5==4&&n%6==5&&n%7==0)
{
printf("%d\n",n);break;
}
elsen++;
}
return0;
}
运行结果如下:
3.利用分治法求一组数据中最大的两个数和最小的两个数。
问题分析:
用n表示输入的数,最大的两个数和最小的两个数可用循环进行情况列举。
算法设计:
用分治法可以用较少的比较次数解决上述问题。
问题可以简化为求最大值和最小值,再把这种情况除外,再求其最大值和最小值。
算法分析:
算法中需要n-1次比较,才能得到第一个最大最小值,需要n-2次比较得到第二个最大最小值。
数据结构设计:
把输入的数存入一维数组ch[],首先对两个数进行比较,然后大的数或者小的数同下一个比较,直到输出最大的数max1和最小的数min1;下一次继续进行循环比较,输出最大的数max2和最小的数min2。
算法如下:
#include
intmain(void)
{
intch[20],n,i,max1=0,max2=0,min1=0,min2=0;
scanf("%d",&n);
for(i=0;iscanf("%d",&ch[i]);
for(i=0;i{
if(ch[max1]max1=i;
if(ch[min1]>ch[i])
min1=i;
}
if(max1==0)
max2=1;
if(min1==0)
min2=1;
for(i=0;i{
if(i==max1||i==min1)
continue;
if(ch[max2]max2=i;
if(ch[min2]>ch[i])
min2=i;
}
printf("max1=%dmax2=%dmin1=%dmin2=%d",ch[max1],ch[max2],ch[min1],ch[min2]);
return0;
}
4.等分液体,在一个瓶子中装有8N(N为偶数)升汽油,要平均分成两份,但只有一个装3(N/2-1)升的量杯和装5(N/2+1)升的量杯(都没有刻度)。
打印出所有把汽油分成两等份的操作过程。
若无解打印“NO”,否则打印操作过程。
问题分析:
将8升汽油平分装入两个不同容量的容器,在没有刻度的情况下,一次就平分是不行的,需要利用容器的差异性多次进行最后达到平分,可以通过分析具体情况达到目的。
算法设计:
利用深度优先算法进行搜索,不满足均分条件时则及时进行回溯,当满足问题的解则结束。
算法分析:
这个算法比较简单,利用条件分支进行判断,来保证不漏判。
数据结构分析:
将三个容器的容量定义为常量,在定义两个变量b和c来确定瓶中实际的重量。
根据确定量的不同情况进行分配,最后达到均分的效果。
算法如下:
#include
intp=4;
intmain()
{
inta=8,y=3,z=5;
voidfen(inta,inty,intz);
fen(a,y,z);
fen(a,z,y);
return0;
}
voidfen(inta,inty,intz)
{
intb=0,c=0;
printf("a:
%db:
%dc:
%d\n",a,y,z,a,b,c);
while(a!
=p||b!
=p&&c!
=p)
{
if(!
b)
{
a-=y;
b=y;
}
else
if(c==z)
{
a+=z;
c=0;
}
else
if(b>z-c)
{
b-=(z-c);
c=z;
}
else
{
c+=b;
b=0;
}
printf("%5d%5d%5d\n",a,b,c);
}
}
程序运行结果: