C++ 搜索之递归

例题1:

附C++代码:

//
//  1458.cpp
//  汉诺塔III
//
//  Created by chenmeiqi on 2019/4/12.
//  Copyright © 2019年 chenmeiqi. All rights reserved.
//

#include <iostream>
using namespace std;

long long F(int x){         // 递归函数。返回值较大用 long long 类型
    if(x==1){       // 参数为1时直接返回2
        return 2;
    }
    else{
        return 3*F(x-1)+2;      // 否则递归调用
    }
}

int main(int argc, const char * argv[]) {
    int n;
    while (cin>>n){
        cout << F(n) <<endl;
    }
    return 0;
}

例题2

//
// 1459.cpp
//  Prime ring problem
//
//  Created by chenmeiqi on 2019/4/12.
//  Copyright © 2019年 chenmeiqi. All rights reserved.
//

#include <iostream>
using namespace std;
int n;
int ans[17];            // 保存环中每一个被放入的数
bool mark[17];          // 标记之前已经被放入环中的数
bool isPrime(int x){            // 判断一个数是否是素数
    for(int i=2;i<x;i++){
        if(x%i==0){
            return false;
        }
    }
    return true;
}

void check(){
    if(isPrime(ans[n]+ans[1])==false){          // 判断最后一个数与第一个数的和是否为素数,若不是则直接返回
        return;
    }
    for(int i=1;i<=n;i++){      // 输出解,注意最后一个数字没有空格
        if(i==1){
            cout<<ans[i];
        }
        else{
            cout<<" "<<ans[i];
        }
    }
    cout<<endl;
}

void DFS(int x){        // 递归枚举,num为当前已经放入环中的数字
    if(x>1){        // 当放入的数字大于 1 个时
        if(isPrime(ans[x]+ans[x-1])==false){        // 判断最后两个数字的和是否为素数,若不是则返回继续枚举第num个数
            return;
        }
    }
    if(x==n){       // 若已经放入了n个数
        check();        // 检查输出
        return;         // 返回,继续枚举下一组解
    }
    for(int i=2;i<=n;i++){      // 放入一个数
        if(mark[i]==false){        // 若i还没有被放入环中
            mark[i]=true;       // 标记i为已经使用
            ans[x+1]=i;     // 将这个数字放入ans数组中
            DFS(x+1);       // 继续尝试放入下一个数
            mark[i]=false;      // 当回溯枚举这位数字时,将i重新标记为未使用
        }
    }
}

int main(int argc, const char * argv[]) {
    int count=0;            // 标记Case数
    while (cin>>n){
        count++;        // Case数递增
        cout<<"Case "<<count<<":"<<endl;
        for(int i=0;i<17;i++){      // 初始化标记所有数字为未被使用
            mark[i]=false;
        }
        ans[1]=1;           // 第一个数字恒定为1
        mark[1]=true;       // 标记1被使用
        DFS(1);             // 继续尝试放入下一个数字
        cout<<endl;
    }
    return 0;
}


例题3: 

附C++代码:

//
//  main.cpp
//  Deposit
//
//  Created by chenmeiqi on 2019/4/15.
//  Copyright © 2019年 chenmeiqi. All rights reserved.
//

#include <iostream>
using namespace std;
char pos[100][100];
bool mark[100][100];
int go[][2]={
    0,1,
    0,-1,
    1,0,
    1,1,
    1,-1,
    -1,0,
    -1,1,
    -1,-1
};
int m,n;
void DFS(int x,int y){
    int nx,ny;
    for(int i = 0; i < 8; i++)
    {
        nx=x+go[i][0];
        ny=y+go[i][1];
        if(nx<0||nx>n||ny<0||ny>m){
            continue;
        }
        if(pos[nx][ny]=='*'){
            continue;
        }
        if(mark[nx][ny]==true){
            continue;
        }
        mark[nx][ny]=true;
        
        DFS(nx,ny);
    }
    return;
}
int main(int argc, const char * argv[]) {
    int count;
    while(cin>>m>>n){
        count=0;
        if(m==0){
            break;
        }
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                cin>>pos[i][j];
                mark[i][j]=false;
            }
        }
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                if(pos[i][j]=='@'&&mark[i][j]==false){
                    DFS(i,j);
                    count++;
                }
            }
        }
        cout<<count<<endl;
    }
}
v


例题4:

代码:

//
//  1461.cpp
//  Temple of the bone
//
//  Created by chenmeiqi on 2019/4/16.
//  Copyright © 2019年 chenmeiqi. All rights reserved.
//

#include <iostream>
using namespace std;
char maze[7][7];        // 保存地图信息
int n,m,t;          // 地图大小为n*m,从起点到终点能否恰好t秒
int go[][2]={               // 四个方向行走坐标差
    1,0,
    -1,0,
    0,1,
    0,-1
};
bool flag;          // 是否成功
void DFS(int x,int y,int res_t){        // 递归形式的深度优先搜索
    int nx,ny;
    for(int i=0;i<4;i++){       // 枚举四个相邻位置
        nx=x+go[i][0];
        ny=y+go[i][1];          // 计算其坐标
        if(nx<0||nx>=n||ny<0||ny>=m){           // 坐标在地图外
            continue;
        }
        if (maze[nx][ny]=='X') {            // 该位置为墙
            continue;
        }
        if(maze[nx][ny]=='D'){          // 该位置为门
            if(res_t+1==t){         // 所用时间恰好为t
                flag=true;          // 搜索成功
                return;     // 返回
            }
            else{           // 否则该状态的后续状态不可能为答案(经过的点不能再经过)
                continue;
            }
        }
        maze[nx][ny]='X';       // 该状态扩展而来的后续状态中,该位置都不能被经过,直接修改该位置为墙
        DFS(nx,ny,res_t+1);     // 递归z扩展该状态,所用时间递增
        maze[nx][ny]='.';       // 若其后续状态全部遍历完毕,则退回上层状态,将因为要搜索其后续状态而改成墙的位置,改回普通位置
        if (flag) {     // 假如已经成功,则直接返回,停止搜索
            return;
        }
    }
}
int main(int argc, const char * argv[]) {
    int sx,sy;
    int dx,dy;
    string s;
    while(cin>>n>>m>>t){
        if(n==0&&m==0&&t==0){
            break;
        }
        for(int i = 0; i < n; i++)
        {
            cin>>s;
            for(int j = 0; j < m; j++)
            {
                maze[i][j]=s[j];
                if(maze[i][j]=='S'){            // 找到起点位置
                    sx=i;
                    sy=j;
                }
                if(maze[i][j]=='D'){            // 找到终点位置
                    dx=i;
                    dy=j;
                }
            }
        }
        flag=false;
        if (((sx+sy)%2+t%2)%2 == (dx+dy)%2 ) {      // 判断S与D的奇偶关系是否与t符合,若不符合直接跳过搜索
            maze[sx][sy]='X';       // 将起点标记为墙
            DFS(sx,sy,0);           // 递归扩展初始状态
        }
        if(flag){
            cout<<"YES"<<endl;
        }
        else{
            cout<<"NO"<<endl;
        }
    }
    return 0;
}

 

另附此题的堆栈解法:

//
//  1461.cpp
//  Temple of the bone 2
//
//  Created by chenmeiqi on 2019/4/16.
//  Copyright © 2019年 chenmeiqi. All rights reserved.
//

#include <iostream>
#include <stack>
using namespace std;
struct N{
    int x;
    int y;
    int t;
};
stack<N> S;
int go[][2]={
    1,0,
    -1,0,
    0,1,
    0,-1,
};
char maze[7][7];
int n,m,t;
bool flag;
void DFS(){
    int nx,ny;
    while (!S.empty()) {
        N now=S.top();
        S.pop();
        for (int i=0; i<4; i++) {
            nx=now.x+go[i][0];
            ny=now.y+go[i][1];
            if (nx<0||nx>=n||ny<0||ny>=m) {
                continue;
            }
            if (maze[nx][ny]=='X') {
                continue;
            }
            if (maze[nx][ny]=='D' && now.t+1==t) {
                flag=true;
                return;
            }
            maze[nx][ny]='X';
            N tmp;
            tmp.x=nx;
            tmp.y=ny;
            tmp.t=now.t+1;
            S.push(tmp);
        }
    }
};
int main(int argc, const char * argv[]) {
    string s;
    int sx,sy;
    int dx,dy;
    while (cin>>n>>m>>t) {
        flag=false;
        if (n==0 && m==0 && t==0) {
            break;
        }
        for (int i=0; i<n; i++) {
            cin>>s;
            for (int j=0; j<m; j++) {
                maze[i][j]=s[j];
                if (s[j]=='S') {
                    sx=i;
                    sy=j;
                }
                if(s[j]=='D'){
                    dx=i;
                    dy=j;
                }
            }
        }
        while (!S.empty()) {
            S.pop();
        }
        maze[sx][sy]='X';
        N begin;
        begin.x=sx;
        begin.y=sy;
        begin.t=0;
        S.push(begin);
        if(((sx+sy)%2 + t%2)%2 ==(dx+dy)%2){
            DFS();
        }
        if(flag){
            cout<<"YES"<<endl;
        }
        else{
            cout<<"NO"<<endl;
        }
    }
    return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值