2.1穷竭搜索

来源:互联网 发布:网络大电影受众分析 编辑:程序博客网 时间:2024/06/03 13:17

穷竭搜索是将所有的可能性罗列出来,在其中寻找答案的方法。

2.1.1递归函数

在一个函数中再次调用改函数自身的行为叫做递归,这样函数被称为递归函数。例如,我们想要编写一个计算阶乘的函数 int fact(int n),当然,用循环也可以

int fact(int n){    if(n==0)        return 1;    return n*fact(n-1);}
2.1.2栈

2.1.3队列

2.1.4深度优先搜索

深度优先搜索是搜索的手段之一。他从某个状态开始,不断转移状态。。。根据深度优先搜索的特点,采用递归函数比较简单

eg 部分和问题

int a[MAX_N];int n,k;//已结从前i项得到了和sum,然后对第i项之后进行分支bool dfs(int i,int sum){    //如果前n项都计算过了,则返回sum是否与k相等    if(i==n)        return sum==k;        if(dfs(i+1,sum))        return true;        if(dfs(i+1,sum+a[i]))        return true;        return false;}void solve(){    if(dfs(0,0))        printf("Yes\n");    else        printf("No\n");}
eg Lake Counting

int N,M;char field[MAX_N][MAX_M+1];//现在位置(x,y)void dfs(int x,int y){    field[x][y]='.';        //8个方向    for(int dx=-1;dx<=1;dx++)    {        for(int dy=-1;dy<=1;dy++)        {            int nx=x+dx;            int ny=y+dy;            if(0<=nx&&nx<N&&0<=ny&&ny<M&&field[nx][ny]=='W')                dfs(nx,ny);        }    }    return;}void solve(){    int res=0;    for(int i=0;i<N;i++)    {        for(int j=0;j<M;j++)        {            if(field[i][j]=='W')            {                dfs(i,j);                res++;            }        }    }    printf("%d\n",res);}
2.1.5 宽度优先搜索

宽度优先搜索总是搜索距离初始状态近的状态。

eg 迷宫的最短路径

const int INF=100000000;//使用pair表示状态时,使用typedef会更加方便一些typedef pair<int,int>P;char maze[MAX_N][MAX_M+1];int N,M;int sx,sy;int gx,gy;int d[MAX_N][MAX_M];int dx[4]={1,0,-1,0},dy[4]={0,1,0,-1};int dfs(){    queue<P>que;    for(int i=0;i<N;i++)        for(int j=0;j<M;j++)            d[i][j]=INF;    que.push(P(sx,sy));    d[sx][sy]=0;        while(que.size())    {        P p=que.front();        que.pop();                if(p.first==gx&&p.second==gy)            break;                for(int i=0;i<4;i++)        {            int nx=p.first+dx[i],ny=p.second+dy[i];            if(0<=nx&&nx<N&&0<=ny&&ny<M&&maze[nx][ny]!='#'&&d[nx][ny]==d[nx][ny]==INF)            {                que.push(P(nx,ny));                d[nx][ny]=d[p.first][p.second]+1;            }        }    }    return d[gx][gy];}void solve(){    int res=bfs();    printf("%d\n",res);}

2.1.6特殊状态的枚举

虽然生成可行解空间多数采用深度优先搜索,但在状态空间比较特殊时其实可以简短地实现,比如,next_permutation这一函数,可以把n个元素共n!种不同的排列生成出来。又或者,使用为运算,可以枚举从n个元素中取出k个的共C 种状态或是某个集合中的全部子集。(3.2节)

bool used[MAX_N];int perm[MAX_N];void permutation1(int pos,int n){    if(pos==n)    {        /*        这里编写需要对perm进行操作        */        return;    }    //针对perm的第POS个位置,究竟使用0~n-1中的那一个进行循环    for(int i=0;i<n;i++)    {        if(!used[i])        {            perm[pos]=i;            used[i]=true;            permutation1(pos+1,n);            used[i]=false;        }    }    return;}#include<algorithm>//即使有重复的元素也会生成所有的排列int perm2[MAX_N];void permutation2(int n){    for(int i=0;i<n;i++)    {        perm2[i]=i;    }    do    {        /*        */    }while(next_permutation(perm2,perm2+n));    return;}

2.1.7剪枝






0 0
原创粉丝点击