要求:
项目数n与各项目的时间与前期项目关系可动态输入(在设计阶段可在程序中暂时给定)。
选作题:
1大数阶乘
对给定的n(n≤100),计算并输出k!
(k=1,2,……,n)的全部有效数字,因k!
的值可能很大,故采用一维数组存计算结果。
设数组的每个元素存储k!
的一位数字,并约定从低位到高位依次存于数组的第一个位置、第二个位置、……。
例如,5!
=120,在数组a中的存储形式为:
a[2]
a[1]
a[0]
…
1
2
0
提示:
计算k!
采用对已求得的(k-1)!
的结果连续累加k-1次后求出。
例如,4!
=24,则计算5!
对原来的24再累加4次24后得到120。
为了控制累加的位数,另引入整型变量用于记录当前(k-1)!
的位数。
2银行卡问题
某银行共发出M张储蓄卡,每张储蓄卡拥有唯一的卡号,每天每张储蓄卡至多支持储蓄卡持有者的N笔“存款”或“取款”业务。
可用数组card[M][N+3]中的每一行存放一张储蓄卡的有关信息,其中:
card[i][0]存放第i张卡的卡号;
card[i][1]存放第i张卡的余额;
card[i][2]存放第i张卡的当日业务实际发生笔数;
card[i][3]~card[i][N+2]存放第i张卡的当日存取款金额,正值代表存款,负值代表取款。
当持卡者输入正确的卡号、存款或取款金额后,程序进行相应的处理;若输入了不正确的数据,程序会提示持卡者重新输入;若输入的卡号为负数时,银行终止当日业务。
3数组压缩
设某个非负整数数组中存在许多连续相等的整数段,编写程序将这样的数组按下列规则压缩到另一整数数组中:
(1)一个连续相等的整数段,如有C(>1)个连续相等整数,在压缩数组中存入C和这个整数。
(2)一个不连续相等的整数段,如有C(C>1)个整数,其中每个整数与其相邻的整数不等,在压缩文件中存入-C和这C个整数。
例如,原数组为
222444838111121
则它的压缩数组为
3234-383841-221
4找最长相同单字
从给定的两个由英文单字(词)组成的字符串s和t中,找出其中都包含的最长的相同单字(同一字母的大小写视作不同字符)。
约定单字全由英文字母组成,单字之间由一个或多个空白符分隔。
提示:
可自左至右顺序扫视字符串s,逐个找出单字(单字开始位置和单字长度),当该单字的长度比已找到的单字更长时,就从头至尾扫视字符串t,在从t中找出与该单字长度相等、字符相同的单字后,登录该单字的开始位置和长度,并回到s,在其中找一个更长的单字,上述寻找过程直至字符串s扫视结束,最后输出找到的单字。
5寻找长整数
设A的个位数a[0]为指定的数p(取值分别为2,3,4,…,9,)。
若将A的个位数字移到其他各位数字之前,则其数值为原数值的A的p倍。
例如,p为4,则A为102564(各位数字分别存入a[5],a[4],…,a[0]之中),有102564*4=410256。
寻找从a[0]=p出发,用p乘已确定的位数的数值可推出其前1的数字,逐位进行,直到用P乘a[n-1]等于a[0],递推计算结束,A即为:
a[n-1]a[n-2]……a[0]
数据结构与算法
课程设计报告
专业班级:
学号:
姓名:
日期:
实例报数问题
1.问题描述
设有n个人围坐一圈并按顺时针方向1-n循环报数。
若从第1个人开始报数,凡是报的数字是7的倍数(如14、49)或其中包含7(如17、71),则此人出圈,再从他的下一个人继续报数,如此进行下去,直到只有一个人为止。
设计程序,要找到那个能留到最后的人的原始位置号与最后应该报的数字。
2.算法分析与设计
3.参考程序
4.运行结果
图是由本程序计算出的3个传教士和3个野人的安全渡河方案。
图14-1野人渡河问题的解答
5.总结与体会
附:
野人渡河程序
3个野人和3个传教士来到河边,打算乘一只船从右岸到左岸去。
该船的负载能力为两人。
在任何时候,如果野人人数超过传教士人数,野人就会把传教士吃掉。
他们怎样才能用这条船安全地把所有人都渡过河去呢?
这个问题还可以拓展为m个野人和n个传教士,而船一次可以装下r个人的情况。
#include
#include
#definemaxloop100//最大层数
#definepristnum3//传教士默认值
#defineslavenum3//野人默认值
structSPQ
{intsr,pr;//船运行一个来回后河右岸的野人、传教士的人数
intsl,pl;//船运行一个来回后河左岸的野人、传教士的人数
intssr,spr;//回来(由左向右时)船上的人数
intsst,spt;//去时(由右向左时)船上的人数
intloop;//本结点所在的层数
structSPQ*upnode,*nextnode;//本结点的父结点和同层的下一个结点的地址
}spq;
intloopnum;//记录总的扩展次数
intopenednum;//记录已扩展节点个数
intunopenednum;//记录待扩展节点个数
intresultnum;
structSPQ*opened;
structSPQ*oend;
structSPQ*unopened;
structSPQ*uend;
structSPQ*result;
voidinitiate();
voidreleasemem();
voidshowresult();
voidaddtoopened(structSPQ*ntx);
intsearch();
voidgoon();
intstretch(structSPQ*ntx);
voidrecorder();
voidmain()
{intflag;//标记扩展是否成功
for(;;)
{initiate();
flag=search();
if(flag==1)
{recorder();
releasemem();
showresult();
goon();
}
else
{printf("无法找到符合条件的解");
releasemem();
goon();
}
}
}
voidinitiate()
{intx;
charchoice;
uend=unopened=(structSPQ*)malloc(sizeof(spq));
if(uend==NULL)
{printf("\n内存不够!
\n");
exit(0);
}
unopenednum=1;
openednum=0;
unopened->upnode=unopened;//保存父结点的地址以成链表
unopened->nextnode=unopened;
unopened->sr=slavenum;
unopened->pr=pristnum;
unopened->sl=0;
unopened->pl=0;
unopened->sst=0;
unopened->spt=0;
unopened->ssr=0;
unopened->spr=0;
unopened->loop=0;
printf("题目:
设有n个传教士和m个野人来到河边,打算乘一只船从右岸到左岸去。
\n");
printf("该船的负载能力为两人。
在任何时候,如果野人人数超过传教士人数,野人\n");
printf("就会把传教士吃掉。
他们怎样才能用这条船安全地把所有人都渡过河去呢-\n");
printf("\n默认的n、m值皆为3\n");
for(;;)
{printf("\n是否修改?
(Y/N):
");
scanf("%s",&choice);
choice=toupper(choice);
if(choice=='Y')
{printf("\n请输入传教士人数:
");
for(;;)
{scanf("%d",&x);
if(x>0)
{unopened->pr=x;
break;
}
elseprintf("\n输入值应大于0!
\n请重新输入");
}
printf("请输入野人人数:
");
for(;;)
{scanf("%d",&x);
if(x>0)
{unopened->sr=x;
break;
}
elseprintf("\n输入值应大于0!
\n请重新输入");
}
break;
}
if(choice=='N')break;
}
}
intsearch()
{intflag;
structSPQ*ntx;//提供将要扩展的结点的指针
for(;;)
{ntx=unopened;//从待扩展链表中提取最前面的一个
if(ntx->loop==maxloop)return0;
addtoopened(ntx);//将ntx加入已扩展链表,并将这个节点从待扩展链表中去掉
flag=stretch(ntx);//对ntx进行扩展,返回-1,0,1
if(flag==1)return1;
}
}
intstretch(structSPQ*ntx)
{intfsr,fpr;//在右岸上的人数
intfsl,fpl;//在左岸上的人数
intsst,spt;//出发时在船上的人数
intssr,spr;//返回时船上的人数
structSPQ*newnode;
for(sst=0;sst<=2;sst++)//讨论不同的可能性并判断是否符合条件
{fsr=ntx->sr;
fpr=ntx->pr;
fsl=ntx->sl;
fpl=ntx->pl;
if((sst<=fsr)&&((2-sst)<=fpr))//满足人数限制
{spt=2-sst;
fsr=fsr-sst;
fpr=fpr-spt;
if((fpr==0)&&(fsr==0))//搜索成功
{newnode=(structSPQ*)malloc(sizeof(spq));
if(newnode==NULL)
{printf("\n内存不够!
\n");
exit(0);
}
newnode->upnode=ntx;//保存父结点的地址以成链表
newnode->nextnode=NULL;
newnode->sr=0;
newnode->pr=0;
newnode->sl=opened->sr;
newnode->pl=opened->pr;
newnode->sst=sst;
newnode->spt=spt;
newnode->ssr=0;
newnode->spr=0;
newnode->loop=ntx->loop+1;
oend->nextnode=newnode;
oend=newnode;
openednum++;
return1;
}
elseif((fpr-fsr)*fpr>=0)//判断是否满足传教士人数大于或等于野人人数
{fsl=fsl+sst;
fpl=fpl+spt;
for(ssr=0;ssr<=1;ssr++)//返回
{intffsl,ffpl;
if((ssr<=fsl)&&((1-ssr)<=fpl))
{spr=1-ssr;
ffsl=fsl-ssr;
ffpl=fpl-spr;
if((ffpl-ffsl)*ffpl>=0)//若符合条件则分配内存并赋值
{intffsr,ffpr;
ffsr=fsr+ssr;
ffpr=fpr+spr;
newnode=(structSPQ*)malloc(sizeof(spq));
if(newnode==NULL)
{printf("\n内存不够!
\n");
exit(0);
}
newnode->upnode=ntx;//保存父结点的地址
newnode->sr=ffsr;
newnode->pr=ffpr;
newnode->sl=ffsl;
newnode->pl=ffpl;
newnode->sst=sst;
newnode->spt=spt;
newnode->ssr=ssr;
newnode->spr=spr;
newnode->loop=ntx->loop+1;
uend->nextnode=newnode;
uend=newnode;
unopenednum++;
}
}
}}}}
return0;
}
voidaddtoopened(structSPQ*ntx)
{unopened=unopened->nextnode;
unopenednum--;
if(openednum==0)
oend=opened=ntx;
oend->nextnode=ntx;
oend=ntx;
openednum++;
}
voidrecorder()
{inti,loop;
structSPQ*newnode;
structSPQ*ntx;
loop=oend->loop;
ntx=oend;
resultnum=0;
for(i=0;i<=loop;i++)
{newnode=(structSPQ*)malloc(sizeof(spq));
if(newnode==NULL)
{printf("\n内存不够!
\n");
exit(0);
}
newnode->sr=ntx->sr;
newnode->pr=ntx->pr;
newnode->sl=ntx->sl;
newnode->pl=ntx->pl;
newnode->sst=ntx->sst;
newnode->spt=ntx->spt;
newnode->ssr=ntx->ssr;
newnode->spr=ntx->spr;
newnode->nextnode=NULL;
ntx=ntx->upnode;
if(i==0)
result=newnode;
newnode->nextnode=result;
result=newnode;
resultnum++;
}
}
voidreleasemem()
{inti;
structSPQ*nodefree;
for(i=1;i{nodefree=opened;
opened=opened->nextnode;
free(nodefree);
}
for(i=0;i{nodefree=unopened;
unopened=unopened->nextnode;
free(nodefree);
}
}
voidshowresult()
{inti;
intfsr,fpr;//在右岸上的人数
intfsl,fpl;//在左岸上的人数
structSPQ*nodefree;
printf("\n");
printf("%d个传教士和%d个野人渡河:
",result->pr,result->sr);
for(i=1;i{nodefree=result;
result=result->nextnode;
free(nodefree);
printf("\n\n\t左岸人数船上人数及方向右岸人数\n");
printf("第%d轮\n",i);
fpl=result->pl-result->spt+result->spr;
fpr=result->pr-result->spr;
fsl=result->sl-result->sst+result->ssr;
fsr=result->sr-result->ssr;
printf("传教士%8d%8d\t<-\t%8d\n",fpl,result->spt,fpr);
printf("野人%8d%8d\t<-\t%8d\n",fsl,result->sst,fsr);
printf("传教士%8d%8d\t->\t%8d\n",result->pl,result->spr,result->pr-result->spr);
printf("野人%8d%8d\t->\t%8d\n",result->sl,result->ssr,result->sr-result->ssr);
}
printf("\n全体传教士和野人全部到达对岸!
");
free(result);
}
voidgoon()
{charchoice;
for(;;)
{printf("\n是否继续?
(Y/N):
");
scanf("%s",&choice);
choice=toupper(choice);
if(choice=='Y')break;
if(choice=='N')exit(0);
}
}