曾经沧海难为水,除却巫山不是云。|

Joey-Wang

园龄:4年3个月粉丝:17关注:0

8.1 DFS

8.1 DFS

http://codeup.hustoj.com/contest.php?cid=100000608

B 【递归入门】组合的输出

image-20200824041227376

题目解析

这题实际是递归求全排列的变体

🆚 求全排列

  1. 全排列每次从n个数中选择一个没选过的,最后组成n个数的序列;此处从n个数中选择一个没选过的,最后组成r个数的序列
  2. 全排列中对n个数序列之间的顺序无要求;此处是组合,也就是不要重复的序列,可通过添加限制要求:后一个数一定比前一个数大实现——x>=p[index-1]

代码

#include <cstdio>
#define maxn 25
int n, r, p[maxn];
bool hashtable[maxn] = {false};

void generateP(int index) {
    if (index == r + 1) {
        for (int i = 1; i <= r; i++) {
            printf("%d ", p[i]);
        }
        printf("\n");
        return;
    }
    for (int x = 1; x <= n; x++) {
        if (!hashtable[x] && x >= p[index - 1]) {
            p[index] = x;
            hashtable[x] = true;
            generateP(index + 1);
            hashtable[x] = false;
        }
    }
}

int main() {
    while (scanf("%d%d", &n, &r) != EOF) {
        generateP(1);
    }
    return 0;
}

E【递归入门】出栈序列统计

image-20200824041717626

题目解析

题目意思:输入n接下来模拟栈的入栈、出栈操作,需要得到入栈n次,出栈n次。问有几种不同的操作顺序
(一开始愣是没读懂题目啥意思😂)

设入栈次数in_num,出栈次数out_num
所以DFS岔路口是选择入栈还是出栈。
若in_num > n || out_num > n 到达死胡同,in_num == n && out_num == n 表示终点。其他都是岔路口。
但需注意的是,只有 in_num > out_num 时才能出栈

代码

#include <cstdio>
#include <stack>

using namespace std;
stack<int> s;
int n, ans = 0;

//in_num表示入栈次数,out_num表示出栈次数
void DFS(int in_num, int out_num) {
    if (in_num == n && out_num == n) {
        ans++;
        return;
    }
    if (in_num > n || out_num > n) return;
    if (in_num < n) DFS(in_num + 1, out_num); //入栈
    if (in_num > out_num && out_num < n) DFS(in_num, out_num + 1); //出栈
}

int main() {
    scanf("%d", &n);
    DFS(0, 0);
    printf("%d\n", ans);
    return 0;
}

F 【递归入门】走迷宫

image-20200824042426531

题目解析

⚠️

  1. 要弄清楚x,y方向和n、m界限分别是对x还是y
  2. 题目要求按照左上右下方向拓展,这里WA了一次

题外话:这里用bool数组b[i][j]记录点x=i,y=j是否已经走过,但是BFS中用bool数组记录点是否如果队

💡这里代码没有做矩阵有全0行/全0列时肯定无解的剪枝

代码

#include <cstdio>
#include <vector>
using namespace std;
struct node {
    int x, y;
};
int n, m,digit=0;
node S,T, Node;
vector<node> ans;
int a[20][20];//存储迷宫的情况
bool b[20][20] = {false};//每个点有没有走过
int X[4] = {0, -1, 0, 1}; //左上右下
int Y[4] = {-1, 0, 1, 0};

bool judge(int x, int y) {
    if (x < 1 || x > n || y < 1 || y > m) return false;
    if (a[x][y] == 0) return false;
    return true;
}

void DFS(int x, int y) {
    if (x == T.x && y == T.y) {
        for (vector<node>::iterator it = ans.begin();it!=ans.end();it++){
            printf("(%d,%d)",(*it).x,(*it).y);
            if(it<ans.end()-1) printf("->");
            else printf("\n");
        }
        digit++;
        return;
    }
    for (int i = 0; i < 4; i++) {
        int newX = x + X[i];
        int newY = y + Y[i];
        // 结点可以走,且没被走过
        if (judge(newX, newY) && !b[newX][newY]) {
            Node.x = newX;
            Node.y = newY;
            b[newX][newY] = true;
            ans.push_back(Node);
            DFS(Node.x, Node.y);
            ans.pop_back();
            b[newX][newY] = false;
        }
    }
}

int main() {
    scanf("%d%d", &n, &m);
    for (int i =1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            scanf("%d", &a[i][j]);
        }
    }
    scanf("%d%d", &S.x, &S.y);
    scanf("%d%d", &T.x, &T.y);
    b[S.x][S.y]= true;
    ans.push_back(S);
    DFS(S.x,S.y);
    if (digit==0) printf("-1");
    return 0;
}

本文作者:Joey-Wang

本文链接:https://www.cnblogs.com/joey-wang/p/14541179.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Joey-Wang  阅读(48)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
展开