第1章 算法概述(穷举算法)
重要人物:Alan Turing(图灵机)、Donald Knuth(TEX系统)
算法:解决问题的一种方法或一个过程
特性:有穷性(Finiteness)、确定性(Definiteness)、可行性(effectiveness)、输入(Input)、输出(Output)
程序:算法+数据结构
计算时间的渐进表示:
多项式时间算法(polynomial time algorithm):O(1) < O(logn) < O(n) < O(nlogn) < O(n2)< O(n3)
指数时间算法(exponential time algorithm):O(2n) < O(n!) < O(nn)
算法复杂性:算法所需要的计算机资源
时间复杂性:随着问题规模n的增大,算法运行时间与问题规模n的某个函数f(n)增长率相同,记时间复杂度为T(n)=O(f(n))
空间复杂性:算法所需空间大小,记为S(n)=O(f(n)),不消耗辅助空间的操作称为原地操作
渐近分析的记号:渐进上界记号O、渐进下界记号
Ω
\Omega
Ω、非紧上界记号o、非紧下界记号
ω
\omega
ω、紧渐近界记号
Θ
\Theta
Θ
穷举算法
例1. 鸡翁一值钱5,鸡母一值钱3,鸡雏三值钱1。百钱买百鸡,问鸡翁、母、雏各几何?
Cock+Hen+Chick=100
Cock5+Hen3+Chick/3=100
代码:
#include<iostream>
#include<stdlib.h>
#include<math.h>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
int main()
{
int x,y,z;
x=0;
while(x<=20)
{
y=0;
while(y<34)
{
z=100-x-y;
if((5*x+3*y+z*1.0/3)==100)
{
printf("Cock is %d,Hen is %d,Chick is %d\n",x,y,z);
}
y++;
}
x++;
}
return 0;
}
例2. Google方程式
有一个字符组成的等式:WWWDOT - GOOGLE = DOTCOM
1)每个字符代表一个0-9之间的数字;
2)WWWDOT、GOOGLE和DOTCOM都是合法的数字;
3)不能以0开头。请找出一组字符和数字的对应关系,使它们互相替换,并且替换后的数字能够满足等式.
代码1:
/*
暴力搜索(穷举)
*/
#include<iostream>
#include<stdlib.h>
#include<math.h>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
int main()
{
int w,d,o,t,g,l,e,c,m;
int A,B,C;
w=1;
while(w<=9)
{
d=1;
while(d<=9)
{
if(d==w)
{
d++;
continue;
}
o=0;
while(o<=9)
{
if(o==w||o==d)
{
o++;
continue;
}
t=0;
while(t<=9)
{
if(t==w||t==d||t==o)
{
t++;
continue;
}
g=1;
while(g<=9)
{
if(g==w||g==d||g==o||g==t)
{
g++;
continue;
}
l=0;
while(l<=9)
{
if(l==w||l==d||l==o||l==t||l==g)
{
l++;
continue;
}
e=0;
while(e<=9)
{
if(e==w||e==d||e==o||e==t||e==g||e==l)
{
e++;
continue;
}
c=0;
while(c<=9)
{
if(c==w||c==d||c==o||c==t||c==g||c==l||c==e)
{
c++;
continue;
}
m=0;
while(m<=9)
{
if(m==w||m==d||m==o||m==t||m==g||m==l||m==e||m==c)
{
m++;
continue;
}
A=w*100000+w*10000+w*1000+d*100+o*10+t;
B=g*100000+o*10000+o*1000+g*100+l*10+e;
C=d*100000+o*10000+t*1000+c*100+o*10+m;
if(A==(B+C))
{
cout<<"answer: "<<A<<" - "<<B<<" = "<<C<<endl;
}
m++;
}
c++;
}
e++;
}
l++;
}
g++;
}
t++;
}
o++;
}
d++;
}
w++;
}
return 0;
}
代码2:
/*
递归搜索(回溯)
*/
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
typedef struct tagcharitem //数据结构
{
char c;
int value;
} charitem;
charitem a[]= //初始化
{
{'W',-1},{'D',-1},{'O',-1},
{'T',-1},{'G',-1},{'L',-1},
{'E',-1},{'C',-1},{'M',-1}
};
int mark[10]; //标记数组
void search(int cnt) //对字母进行搜索 最后判断下
{
if(cnt==10)
{
int sum1=a[0].value*1e5+a[0].value*1e4+a[0].value*1e3+a[1].value*1e2+a[2].value*10+a[3].value;
int sum2=a[4].value*1e5+a[2].value*1e4+a[2].value*1e3+a[4].value*1e2+a[5].value*10+a[6].value;
int sum3=a[1].value*1e5+a[2].value*1e4+a[3].value*1e3+a[7].value*1e2+a[2].value*10+a[8].value;
if(sum1-sum2==sum3)
cout<<sum1<<"-"<<sum2<<"="<<sum3<<endl;
return;
}
for(int i=9; i>=0; i--) //为字母赋值,W更可能为较大值
{
if(mark[i]!=0) continue;
if((cnt==0||cnt==4||cnt==2)&&i==0) continue; //剪枝:开头为0
a[cnt].value=i;
mark[i]=1;
search(cnt+1);
a[cnt].value=-1;
mark[i]=0;
}
}
int main()
{
memset(mark,0,sizeof(mark));
search(0);
return 0;
}