九种基本算法概论.docx
- 文档编号:29832600
- 上传时间:2023-07-27
- 格式:DOCX
- 页数:23
- 大小:19.88KB
九种基本算法概论.docx
《九种基本算法概论.docx》由会员分享,可在线阅读,更多相关《九种基本算法概论.docx(23页珍藏版)》请在冰豆网上搜索。
九种基本算法概论
九种基本算法思想
一、枚举算法
1、基本思想
枚举法也叫穷举算法,是指将问题的所有可能的结果一一列举,然后根据条件判断是否适合,适合就保留,不是喝酒舍弃;一般采用while循环实现。
2、实例演练
百钱买百鸡问题:
公鸡每只5元,母鸡每只3元,小鸡3元一只。
先用100元钱,买公鸡、母鸡、小鸡各几只?
代码:
#include
intmain()
{
intx,y,z;
for(x=0;x<=20;x++)
{
for(y=0;y<=33;y++)
{
z=100-x-y;
if(z%3==0&&x*5+y*3+z/3==100)
printf("公鸡:
%d,母鸡:
%d,小鸡:
%d\n",x,y,z);
}
}
getch();
return0;
}
二、递推算法
1、算法思想:
具体分两种:
(1)顺推法:
从已知条件入手,逐步推算出要解决问题的方法。
例如斐波那契数列;
(2)逆推法:
从已知的结果出发,利用迭代表达式逐步推算出问题开始的条件;
2.实例演练:
(1)斐波那契数列(兔子的繁殖):
代码:
#include
#defineNUM13
intmain()
{
inti;
longfib[NUM]={1,1};
for(i=2;i { fib[i]=fib[i-1]+fib[i-2]; } for(i=0;i { printf("%d月兔子总数: %d\n",i,fib[i]); } getch(); return0; } (2)母亲为儿子大学四年生活费存了一笔钱,方式是整存零取,规定儿子每月月底取走下月的生活费1000元。 现在假设银行的年利率是1.71%,现在计算母亲至少存多少钱? 代码: #include #defineFETCH1000 #defineRATE0.0171 intmain() { doublecorpus[49]; inti; corpus[48]=(double)FETCH; for(i=47;i>0;i--) { corpus[i]=(corpus[i+1]+FETCH)/(1+RATE/12); } for(i=48;i>0;i--) { printf("第%d月末本利合计: %.2f\n",i,corpus[i]); } getch(); return0; } 三、递归算法 1.算法思想: 就是函数自己调用自己的算法; 2.实例演练: (1)汉诺塔问题: 代码: move(intn,intx,inty,intz) { if(n==1) printf("%c-->%c\n",x,z); else { move(n-1,x,z,y); printf("%c-->%c\n",x,z); {getchar();} move(n-1,y,x,z); } } main() { inth; printf("inputnumber: "); scanf("%d",&h); printf("thesteptomoving%2ddiskes: \n",h); move(h,'a','b','c'); system("pause"); } (2)阶乘问题: 代码: #include intfact(intn); intmain() { inti; printf("请输入要求阶乘的一个整数: "); scanf("%d",&i); printf("%d的阶乘结果为: %d\n",i,fact(i)); getch(); return0; } intfact(intn) { if(n<=1) return1; else returnn*fact(n-1); } 四、分治算法 1.算法思想: 将一个规模为N的问题分解为K个规模较小的问题,这些问题相互独立且与原问题性质相同,我们只需要求出每个子问题的结果就可以得到原问题的结果。 2.实例演练: 大数相乘问题: #include #include #include #include char*result='\0'; intpr=1; voidgetFill(char*a,char*b,intia,intja,intib,intjb,inttbool,intmove){ intr,m,n,s,j,t; char*stack; m=a[ia]-48; if(tbool){//直接从结果数组的标志位填入,这里用了堆栈思想 r=(jb-ib>ja-ia)? (jb-ib): (ja-ia); stack=(char*)malloc(r+4); for(r=j=0,s=jb;s>=ib;r++,s--){ n=b[s]-48; stack[r]=(m*n+j)%10; j=(m*n+j)/10; } if(j){ stack[r]=j; r++; } for(r--;r>=0;r--,pr++) result[pr]=stack[r]; free(stack); for(move=move+pr;pr result[pr]='\0'; } else{//与结果的某几位相加,这里不改变标志位pr的值 r=pr-move-1; for(s=jb,j=0;s>=ib;r--,s--){ n=b[s]-48; t=m*n+j+result[r]; result[r]=t%10; j=t/10; } for(;j;r--){ t=j+result[r]; result[r]=t%10; j=t/10; } } } intget(char*a,char*b,intia,intja,intib,intjb,intt,intmove){ intm,n,s,j; if(ia==ja){ getFill(a,b,ia,ja,ib,jb,t,move); return1; } elseif(ib==jb){ getFill(b,a,ib,jb,ia,ja,t,move); return1; } else{ m=(ja+ia)/2; n=(jb+ib)/2; s=ja-m; j=jb-n; get(a,b,ia,m,ib,n,t,s+j+move); get(a,b,ia,m,n+1,jb,0,s+move); get(a,b,m+1,ja,ib,n,0,j+move); get(a,b,m+1,ja,n+1,jb,0,0+move); } return0; } intmain(){ char*a,*b; intn,flag; a=(char*)malloc(1000); b=(char*)malloc(1000); printf("Theprogramwillcomputera*b\n"); printf("Enterab: "); scanf("%s%s",a,b); result=(char*)malloc(strlen(a)+strlen(b)+2); flag=pr=1; result[0]='\0'; if(a[0]=='-'&&b[0]=='-') get(a,b,1,strlen(a)-1,1,strlen(b)-1,1,0); if(a[0]=='-'&&b[0]! ='-'){ flag=0; get(a,b,1,strlen(a)-1,0,strlen(b)-1,1,0); } if(a[0]! ='-'&&b[0]=='-'){ flag=0; get(a,b,0,strlen(a)-1,1,strlen(b)-1,1,0); } if(a[0]! ='-'&&b[0]! ='-') get(a,b,0,strlen(a)-1,0,strlen(b)-1,1,0); if(! flag) printf("-"); if(result[0]) printf("%d",result[0]); for(n=1;n printf("%d",result[n]); printf("\n"); free(a); free(b); free(result); system("pause"); return0; } 五、贪心算法 1.算法思想: 也叫贪婪法。 在求解问题时总是做出在当下看来是最好的抉择的方法。 2.实例演练 (1)人民币找零问题: #include #defineMAXN9 intparvalue[MAXN]={10000,5000,2000,1000,500,100,50,10}; intnum[MAXN]={0}; intexchange(intn) { inti,j; for(i=0;i if(n>parvalue[i])break;//找到比n小的最大面额 while(n>0&&i { if(n>=parvalue[i]) { n-=parvalue[i]; num[i]++; }elseif(n<10&&n>=5) { num[MAXN-1]++; break; }elsei++; } return0; } intmain() { inti; floatm; printf("请输入找零的金额: "); scanf("%f",&m); exchange((int)100*m); printf("\n%.2f元零钱的组成: \n",m); for(i=0;i if(num[i]>0) printf("%6.2f: %d张\n",(float)parvalue[i]/100.0,num[i]); getch(); return0; } (3)装箱问题: #include #include #defineN6 #defineV100 typedefstructbox { intno; intsize; structbox*next; }BOX; voidinit_list(BOX**H) { *H=(BOX*)malloc(sizeof(BOX)); (*H)->no=0; (*H)->size=0; (*H)->next=NULL; } BOX*find_p(BOX*H,intvolume,intv) { BOX*p=H->next; while(p! =NULL) { if(p->size+volume<=v) break; p=p->next; } returnp; } voidadd_list_tail(BOX*H,BOX*p) { BOX*tmp=H->next; BOX*q=H; while(tmp! =NULL) { q=tmp; tmp=tmp->next; } q->next=p; } voidprint_list(BOX*H) { BOX*p=H->next; while(p! =NULL) { printf("%d: %d\n",p->no,p->size); p=p->next; } } intadd_box(intvolume[],intv) { intcount=0; inti; BOX*H=NULL; init_list(&H); for(i=0;i { BOX*p=find_p(H,volume[i],v); if(p==NULL) { count++; p=(BOX*)malloc(sizeof(BOX)); p->no=count; p->size=volume[i]; p->next=NULL; add_list_tail(H,p); } else { p->size+=volume[i]; } } print_list(H); returncount; } intmain(intargc,char*argv[]) { intret; intvolumes[]={60,45,35,20,20,20}; ret=add_box(volumes,V); printf("%d\n",ret); system("PAUSE"); return0; } 六、动态规划 1.算法思想: 是系统分析算法的一种常用算法,根据时空的特点,将复杂问题分成若干的小阶段,在选定系统上进行方向之后,逆向从终点开始计算,逐次对每个阶段寻找某种策略,使得整个过程达到最优。 通常分成两个阶段: 划分阶段;选择状态。 2.实例演练: 求两个字符串的最长公共子串: #include #include #defineMAXLEN100 voidLCSLength(char*x,char*y,intm,intn,intc[][MAXLEN],intb[][MAXLEN]) { inti,j; for(i=0;i<=m;i++) c[i][0]=0; for(j=1;j<=n;j++) c[0][j]=0; for(i=1;i<=m;i++) { for(j=1;j<=n;j++) { if(x[i-1]==y[j-1]) { c[i][j]=c[i-1][j-1]+1; b[i][j]=0; } elseif(c[i-1][j]>=c[i][j-1]) { c[i][j]=c[i-1][j]; b[i][j]=1; } else { c[i][j]=c[i][j-1]; b[i][j]=-1; } } } } voidPrintLCS(intb[][MAXLEN],char*x,inti,intj) { if(i==0||j==0) return; if(b[i][j]==0) { PrintLCS(b,x,i-1,j-1); printf("%c",x[i-1]); } elseif(b[i][j]==1) PrintLCS(b,x,i-1,j); else PrintLCS(b,x,i,j-1); } intmain(intargc,char**argv) { charx[MAXLEN]={"ABCBDAB"}; chary[MAXLEN]={"BDCABA"}; intb[MAXLEN][MAXLEN]; intc[MAXLEN][MAXLEN]; intm,n; m=strlen(x); n=strlen(y); LCSLength(x,y,m,n,c,b); PrintLCS(b,x,m,n); getch(); return0; } 七、试探算法 1.算法思想 又称回溯法,先暂且放弃关于问题规模大小的限制,并将问题的候选解按照某种次序逐一枚举和检验,当发现当前候选解不可能是正确解时就选择下一个候选解,若是,则扩大当前候选解的规模。 2.实例演练: 八皇后问题: #include #defineN8 intsolution[N],j,k,count,sols; intplace(introw,intcol) { for(j=0;j { if(row-j==solution[row]-solution[j]||row+solution[row]==j+solution[j]||solution[j]==solution[row]) return0; } return1; } voidbacktrack(introw) { count++; if(N==row) { sols++; for(k=0;k printf("%d\t",solution[k]); printf("\n\n"); } else { inti; for(i=0;i { solution[row]=i; if(place(row,i)) backtrack(row+1); } } } voidqueens() { backtrack(0); } intmain(void) { queens(); printf("TotalSolutions: %d\n",sols); getch(); return0; } 八、迭代算法 1.算法思想: 也成辗转法。 不断用变量的旧值递推新值的算法; 2.实例演练: 求平方根: #include #include voidmain() { doublea,x0,x1; printf("Inputa: \n"); scanf("%lf",&a);//为什么在VC6.0中不能写成“scanf("%f",&a);”? if(a<0) printf("Error! \n"); else { x0=a/2; x1=(x0+a/x0)/2; do { x0=x1; x1=(x0+a/x0)/2; }while(fabs(x0-x1)>=1e-6); } printf("Result: \n"); printf("sqrt(%g)=%g\n",a,x1); getch(); return0; } 九、模拟算法 1.算法思想: 模拟算法是最基本的算法,是根据题目的规则对题目进行编程模拟。 例如在C语言中使用srand()初始化随机数发生器,然后利用rand()函数来生成随机数。 2.实例演练: (1)猜数游戏: #include #include intmain() { intn,m,i=0; srand(time(NULL)); n=rand()%100+1; do{ printf("输入所猜数字: "); scanf("%d",&m); i++; if(m>n) printf("错误! 所猜数太大了! \n"); elseif(m printf("错误! 所猜数太小了! \n"); }while(m! =n); printf("答对了! \n"); printf("共猜测了%d次。 \n",i); if(i<=5) printf("你太聪明了,这么快就猜出来了! "); elseif(i>5) printf("还需改进方法,以便更快猜出来! "); getch(); return0; } (2)掷骰子游戏: #include #include voidplay(intn) { inti,m=0,t=0; for(i=0;i { t=rand()%6+1; m+=t; printf("\t第%d粒: %d;\n",i+1,t); } printf("\t总点数为: %d\n",m); } intmain(void) { intc;//参赛人数 intn;//骰子数量 inti,m; do{ srand(time(NULL)); printf("设置骰子数量(输入0退出): "); scanf("%d",&n); if(n==0)break;//至少一个骰子 printf("\n输入本轮参赛人数(输入0退出): "); scanf("%d",&c); if(c==0)break; for(i=0;i { printf("\n第%d位选手掷出的骰子为: \n",i+1); play(n); } printf("\n"); }while (1); return0; }
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 基本 算法 概论