深度优先搜索(DFS)

深度优先搜索

深度优先搜索算法(Depth First Search,简称DFS):一种用于遍历或搜索树或图的算法。
沿着树的深度遍历树的节点,尽可能深的搜索树的分支。当节点v的所在边都己被探寻过或者在搜寻时结点不满足条件,搜索将回溯到发现节点v的那条边的起始节点。整个进程反复进行直到所有节点都被访问为止。属于盲目搜索,最糟糕的情况算法时间复杂度为O(!n)。

1.部分和问题

给定整数a1,a2,…,an,判断是否可以从中选出若干数,使得他们的和恰好等于k

  • 输入1:整数n
  • 输入2:n个整数an
  • 输入3:整数k
样例输入1:                 
4                         
1 2 4 7                  
13                       
样例输出1:                
Yes 
样例输入2:
4
1 2 4 7
15
样例输出2:
No

将a1作为根节点,左边子树为a1被选用的情况,右边子树为a1不被选用的情况,用sum来计算被选数据的和

part_sum.hpp

#ifndef PART_SUM
#define PART_SUM
#include <bits/stdc++.h>
using namespace std;

#define max_N 100000005

class PartSum
{
public:
    bool dfs(int i,int sum);
    void creat();
    void solve();
private:
    int n,k;
    int a[max_N];
};

bool PartSum::dfs(int i,int sum){
    if(i == n){
        return (sum == k);
    }
    //左子树,a[i]被选用的情况
    if(dfs(i + 1, sum + a[i])){
        return true;
    }
    //右子树,a[i]未选用的情况
    if(dfs(i + 1, sum)){
        return true;
    }
    cout << "i = " << i << endl;
    return false;
}

void PartSum::creat(){
    cin >> n;
	for (int i = 0; i < n; i++){
		cin >> a[i];
	}
	cin >> k;

}

void PartSum::solve(){
    if (this->dfs(0,0)){
		cout << "Yes";
	}else{
		cout << "No";
	}
}
#endif

2.八领域积水问题

有一个大小为 M × N 的园子 雨后积起了水 八连通的积水被认为是连接在一起的 请求出园子里共有多少个水洼

  • 第一行输入一个整数N
  • 第二行输入一个整数M
  • 接下来的 M 行 N 列表示园子的范围,其中“w”为积水
样例输入:
w . . . . . . . . w w . 
. w w w . . . . . w w w 
. . . . w w . . . w w . 
. . . . . . . . . w w . 
. . . . . . . . . w . . 
. . w . . . . . . w . . 
. w . w . . . . . w w . 
w . w . w . . . . . w . 
. w . w . . . . . . w . 
. . w . . . . . . . w . 
样例输出:
3

lake_couting.hpp

#ifndef LAKE_COUNTING
#define LAKE_COUNTING

#include <bits/stdc++.h>
using namespace std;

#define max_N 105

class LakeCounting
{
public:
    char field[max_N][max_N];
    int M,N;
public:
    void dfs(int x,int y);
    void solve();
    void creatfield();
};

void LakeCounting::dfs(int x,int y){

    field[x][y] = '.';

    for(int dx = -1; dx <= 1; dx++){
        for(int dy = -1; dy <= 1; dy++){
            int nx = x + dx , ny = y + dy;
            if(nx >= 0 && nx < M && ny >= 0 && ny < N && field[nx][ny] == 'w'){
                dfs(nx,ny);
            }
        }
    }
}

void LakeCounting::solve(){
    int res = 0;
    cout << "M = " << M << " N = " << N << endl;
    for(int i = 0; i < M; i++){
        for(int j = 0; j < N; j++){
            if(field[i][j] == 'w'){
                dfs(i,j);
                res++;
            }
        }
    }
    cout << "lake = " <<  res  << endl;
}

void LakeCounting::creatfield(){
    cout << "请输入园子的长度:";
    cin >> M ;
    cout << "请输入园子的宽度:";
    cin >> N ;
    for(int i = 0; i < M; i++){
        for(int j = 0; j < N; j++){
            cout << "请输入数据:  field[" << i << "][" << j << "] = ";
            cin >> field[i][j];
        }
    }
}
#endif

3.旅行商问题(无向图最短路径遍历)

输入一个无向图,求从起点到终点的所有路径

在这里插入图片描述

转换为矩阵表达

样例输入:
citynum
roadnum
a b c
a b c
a b c
. . .
  • citynum 表示城市数量
  • roadnum 表示路径数量
  • a b c 表示城市 a 和城市 b 可以互相到达,路程为 c 公里

undirected_graph.hpp

#ifndef UNDIRECTED_GRAPH
#define UNDIRECTED_GRAPH
#include <fstream>
#include <iostream>
#include <time.h>
#include <vector>
#include <limits.h>

#define max_N 105
#define inf INT_MAX
using namespace std;

class UndirectedGraph{
    public:
        int input[max_N][3];
        int graph[max_N][max_N];
        int roadnum;
        int min_dist = inf;
        int citynum;
        int cur_dis = 0;
        bool book[max_N];
        vector<int> path;
    public:
        void creat();
        void initial_graph();
        void dfs(int start_id,int end_id,int &min_dis,int cur_dis,int cur_id);
        void findpath();
};
void UndirectedGraph::creat(){
    ifstream file("./undirected.txt");
    if (!file.is_open())
    {
        cout << "打开文件失败,请检查文件路径是否正确" << endl;
    }

    file >> citynum;
    file >> roadnum;
    cout << "citynum = " << citynum << endl;
    cout << "roadnum = " << roadnum << endl;
    for (int i = 0; i < roadnum; i++){
        for (int j = 0; j < 3; j++){
            file >> input[i][j];
            // cout << "input[" << i << "][" << j << "] = " << input[i][j] << endl;
        }
    }
    file.close();
}
void UndirectedGraph::initial_graph(){
    for (int i = 0; i < max_N; i++){
        for (int j = 0; j < max_N; j++){
            if(i == j){
                graph[i][j] = 0;
            }else{
                graph[i][j] = inf;
            }
        }
        book[i] = false;
    }
    for(int i = 0; i < roadnum; i++){
        graph[input[i][0]][input[i][1]] = input[i][2];   
        graph[input[i][1]][input[i][0]] = input[i][2];
    }
    // print graph
    for(int i = 1; i <= citynum; i++){  // graph下标从1开始
        for(int j = 1; j <= citynum; j++){
            if(graph[i][j] == inf){
                cout << setw(4) << "inf" << " ";
            }else{
                cout << setw(4) << graph[i][j] << " ";
            }
        }
        cout << endl;
    }
}

void UndirectedGraph::findpath(){
    dfs(1,5,min_dist,cur_dis,1);
    cout << "min_dist = " << min_dist << endl;
    cout << "THE BEST PATH:" <<  endl;
    for(int i = 0; i < path.size(); i++){
        cout << path[i] ;
        if(path[i] != path.back()){
            cout << " --> ";
        }
    }
    cout << endl;
}
void UndirectedGraph::dfs(int start_id,int end_id,int &min_dis,int cur_dis,int cur_id){
    book[cur_id] = true;
    if(cur_dis > min_dis){
        return;
    }
    if(cur_id == end_id){
        if(cur_dis < min_dis){
            min_dis = cur_dis;
            path.clear();
            for(int k = 1; k <= citynum; k++){
                if(book[k])  path.push_back(k)  ;
            }
        }
        return;
    }
    for(int k = 1; k <= citynum; k++){
        if(!book[k] && graph[cur_id][k] != inf){
            dfs(start_id, end_id, min_dis, cur_dis + graph[cur_id][k], k);
            book[k] = false;
        }
    }
    return;
}
#endif

4.主程序与测试用例

dfs_demo.cpp

/* ***********
 * DFS Algorithm DEMO
 * @Prame
*********** */
#include "dfs_demo/part_sum.hpp"
#include "dfs_demo/lake_couting.hpp"
#include "dfs_demo/undirected_graph.hpp"
int main () {
	//* problem 1
	// PartSum partsum;
	// partsum.solve();

	//* problem 2
	// LakeCounting lakecounting;
	// lakecounting.creatfield();
	// lakecounting.solve();
	
	//* problem 3
	// UndirectedGraph undirectedgraph;
	// undirectedgraph.creat();
	// undirectedgraph.initial_graph();
	// undirectedgraph.findpath();
	return 0;
}

problem3 测试用例
----
undirected.txt

5
7
1 2 2 
1 3 4
1 5 10
2 3 3
3 4 4
3 5 3
4 5 5
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值