八大算法思想

来源:互联网 发布:气象数据 英文缩写 编辑:程序博客网 时间:2024/05/19 10:09


下面介绍一下最常用的八大算法思想

一、比较“笨”的枚举算法

         基本思路:

                   1、确定枚举对象、枚举范围和判定条件
                   2、注意枚举可能的解,验证每个节是否是问题的解

         枚举算法步骤:

                   1、题解的可能范围,补能遗漏任何一个真正解,也要避免有重复

                   2、判断是否真正解的方法

                   3、使可能解的范围降至最小,以便提高解决问题的效率

#include <stdio.h>int main(){int x,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);}}}return 0;}



二、递推算法思想

         1、顺推法:从已知条件出发,逐步推算出要解决问题的方法。(斐波那契数列)

#include <iostream>#include <vector>using namespace std;void get_tuzi(int mouth);int main(){int x,y,z;int mouth;cin>>mouth;get_tuzi(mouth);return 0;}void get_tuzi(int mouth){vector<int> n(mouth);n[0]=0;n[1]=1;for(int i=2;i<mouth+1;i++){n[i]=n[i-1]+n[i-2];}cout<<n[mouth]<<endl;}


         2、逆推法:从已知结果出发,用迭代表达式逐步推算出要解决问题开始的条件,即顺推法的逆过程。

#include <stdio.h>#define FETCH 1000#define RATE  0.0171int main(){double corpus[49];int i;corpus[48]=(double)FETCH;for(i=47;i>0;i--){corpus[i]=(corpus[i+1])/(1+RATE/12)+FETCH;}printf("%.2f",corpus[47]);}


三、递归算法思想

         特点:

                   1、递归过程一般通过函数或子过程来实现。

                   2、递归算法在函数或子过程的内部,直接或者间接地调用自己的算法。、

                   3、递归算法实际上是把问题转化为规模缩小了的同类问题的子问题,然后在递归调用函数或者子过程来表示问题的解。

         注意以下几点:

                   1、递归式在过程或函数中调用自身的过程。

                   2、在使用递归时,必须有一个明确的递归结束条件,称为递归出口

                   3、递归算法通常显得很简洁,但是运行效率低,一般不提倡

                   4、在递归调用过程中,系统用栈来存储每一层的返回点和局部量,如果次数过多。容易溢出,一般不提倡使用。

                   (汉诺塔问题、阶乘问题)

#include <iostream>using namespace std;void hannuo(int n,char a,char b,char c);int main(){int n;cin>>n;hannuo(n,'A','B','C');return 0;}void hannuo(int n,char a,char b,char c){if(n==1)cout<<a<<"-->"<<c<<endl;else{hannuo(n-1,a,c,b);cout<<a<<"-->"<<c<<endl;hannuo(n-1,b,a,c);}}

阶乘:

#include <iostream>using namespace std;int jiecheng(int n);int main(){cout<<jiecheng(2)<<endl;return 0;}int jiecheng(int n){if(n==0) return 1;else {return (jiecheng(n-1)*n);}}


四、分治算法思想

         1、分解,将要解决的问题划分成若干个规模较小的同类问题;

         2、求解,当子问题化分足够小时,用较简单的方法解决;

         3、合并,按原问题的要求,将子问题的解逐层合并构成原问题的解。

                     (大数相乘、比赛日程安排)

#include <stdio.h>#include <malloc.h>#include <string.h>void mult(char a[],char b[],char s[]);void main(){char *a="123",*b="456";char *s=(char *)malloc(sizeof(char)*8);mult(a,b,s);printf("%s\n",s);}void mult(char a[],char b[],char s[]){int i,j,k=0,alen,blen,sum=0,res[65][65]={0},flag=0;char result[65];alen=strlen(a);blen=strlen(b);for (i=0;i<alen;i++)for (j=0;j<blen;j++) res[i][j]=(a[i]-'0')*(b[j]-'0');for (i=alen-1;i>=0;i--){for (j=blen-1;j>=0;j--)sum=sum+res[i+blen-j-1][j];result[k]=sum%10;k=k+1;sum=sum/10;printf("%d\n",result[k-1]);}for (i=blen-2;i>=0;i--){for (j=0;j<=i;j++) sum=sum+res[i-j][j];result[k]=sum%10;k=k+1;sum=sum/10;printf("%d\n",result[k-1]);}if (sum!=0) {result[k]=sum;k=k+1;}for (i=0;i<k;i++) result[i]+='0';for (i=k-1;i>=0;i--) s[i]=result[k-1-i];s[k]='\0';while(1){if (strlen(s)!=strlen(a)&&s[0]=='0')strcpy(s,s+1);elsebreak;}}

#include <iostream>#include <iomanip>using namespace std;int a[65][65]={0};void gamecal(int k,int n);int main(){int n,i,j=2;cin>>n;if(n<=2||n>64) return 0;while(n!=j){j=j*2;if(j>64) return 0;}gamecal(1,n);cout<<left;cout<<setw(5)<<"编号";cout<<right;for(j=2;j<=n;j++)cout<<setw(5)<<j-1<<"天";cout<<endl;for(i=1;i<=n;i++){cout<<left;for(j=1;j<=n;j++)cout<<setw(8)<<a[i][j];cout<<endl;}return 0;}void gamecal(int k,int n){int i,j;if(n==2){a[k][1]=k;a[k][2]=k+1;a[k+1][1]=k+1;a[k+1][2]=k;}else{gamecal(k,n/2);gamecal(k+n/2,n/2);for(i=k;i<k+n/2;i++)for(j=n/2+1;j<=n;j++)a[i][j]=a[i+n/2][j-n/2];for(i=k+n/2;i<k+n;i++)for(j=n/2+1;j<=n;j++)a[i][j]=a[i-n/2][j-n/2];}}


五、贪心算法思想

         从问题的某一个初始解出发,逐步逼近给定的目标,一遍尽快求出更好的解。当达到算法中的某一部不能再继续前进时,就停止算法,给出一个近似解

         存在的问题

                   1、不能保证最后的结果是最优的

                   2、不能用来求最大或最小解的问题

                   3、只能求满足某些约束条件的可行解的范围

         基本思路

                   1、建立数学模型来描述问题

                   2、把求解的问题分成若干个子问题

                   3、把子问题的局部最优解合并成原来界问题的一个解

         基本过程

                   1、从问题的某一初始解出发

                   2、while能向给定总目标前进一步

                   3、求出可行解的一个解元素

                   4、由所有解元素组合成问题的一个可行解。

贪心之钱找零

#include <iostream>#include <iomanip>using namespace std;#define MAXN 9int parvalue[MAXN]={10000,5000,2000,1000,500,100,50,20,10};int num[MAXN]={0};void exchange(int n){int i,j;for(i=0;i<MAXN;i++)if(n>parvalue[i]) break;i--;while(n>0 && i<MAXN){if(n>=parvalue[i]){cout<<"sdsd"<<endl;n=n-parvalue[i];num[i]++;}else if(n<11 && n>=5) {num[MAXN-1]++;break;}else i++;}}int main(){int i;float m;cin>>m;exchange((int)(100*m));for(i=0;i<MAXN;i++){cout<<setiosflags(ios::fixed)<<setprecision(3)<<(double)parvalue[i]/100<<"   "<<num[i]<<endl;}return 0;}

贪心之装箱

#include <stdio.h>#include <stdlib.h>#define N 6#define V 100typedef struct box{int no;int size;struct box *next;}BOX;void init_list(BOX **H){*H=(BOX *)malloc(sizeof(BOX));(*H)->no=0;(*H)->size=0;(*H)->next=NULL;}BOX* find_p(BOX *H,int volume){BOX *p=H->next;while(p!=NULL){if(p->size+volume<=V) break;p=p->next;}return p;}void add_list_tail(BOX *H,BOX *p){BOX *tmp=H->next;BOX *q=H;while (tmp!=NULL){q=tmp;tmp=tmp->next;}q->next=p;}void print_list(BOX *H){BOX *p=H->next;while(p!=NULL){printf("%d:%d\n",p->no,p->size);p=p->next;}}int add_box(int volume[]){int count=0;int i;BOX *p;BOX *H=NULL;init_list(&H);for(i=0;i<N;i++){p=find_p(H,volume[i]);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);return count;}int main(){int ret;int volume[]={60,45,35,20,20,20};ret=add_box(volume);printf("%d\n",ret);return 0;}


六、试探算法思想

         1、针对所给问题,定义问题的解空间。

         2、确定易于搜索的解空间结构

         3、以深度优先搜索空间,并在搜索过程中用剪枝函数避免无效搜索。`

经典例子:八皇后

#include <stdio.h>#define N 8int set[N],count,sols;int judge_place(int row){int j;for(j = 0;j < row;j++)if(row - j == set[row] - set[j] || row + set[row] == j + set[j] || set[row] == set[j])//(1)判断是否在同一下斜线上(2)判断是否在同一上斜线上(3)判断是否在同一列上return 0;return 1;}void place(int row){int i;if(row == N){sols++;for(i=0;i<N;i++)printf("%d\t",set[i]);printf("\n");}else for(i=0;i<N;i++){set[row]=i;if(judge_place(row))place(row+1);}}int main(){place(0);printf("共有%d方案:\n",sols);return 0;}


七、迭代算法

         1、确定迭代变量:在可以使用迭代算法解决的问题中,至少存在一个迭代变量,即直接或间接地不断有救治递推出心智的变量。

         2、建立迭代关系式:迭代关系式

求近似平方根

#include <iostream>#include <cmath>using namespace std;int main(){double a,x0,x1;cin>>a;if(a<0) {cout<<"Error!"<<endl;return 0;}x0 = a / 2;x1 = (x0 + a / x0) / 2;while (fabs(x0-x1) >= 1e-6){x0=x1;x1 = (x0 + a / x0) / 2;}cout<<"sart(a) = "<<x1<<endl;return 0;}


八、模拟算法思想

         模拟是对真实事物或者过程的虚拟。在编程时为了实现某个功能,可以用语言来模拟该功能,模拟成功也就相应的表示编程的成功


0 0
原创粉丝点击