深度优先搜索

Posted Keep--Silent

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深度优先搜索相关的知识,希望对你有一定的参考价值。

深度优先搜索:Depth First Search
视频链接

本文讲解以DFS解决校选
深度优先搜索常常复杂度较大,所以需要根据题目的题意进行适当剪枝

中档题-2 勋总的幂集 (15 分)

链接
dfs:15分

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

set<vector<int>> ans;
int num[20];
void dfs(int pos, int n, vector<int> v)

    //pos:第pos个数
    //一共n个数,
    //前面的集合是v
    if (pos >= n)
    
        ans.insert(v);
        return;
    
    dfs(pos + 1, n, v);
    v.push_back(num[pos]);
    dfs(pos + 1, n, v);

int main()


    int n;
    cin >> n;
    for (int i = 0; i < n; i++)
    
        cin >> num[i];
    
    vector<int> v;
    dfs(0, n, v);
    for (auto it : ans)
    
        for (int i = 0; i < it.size(); i++)
        
            printf("%d%s", it[i], i == it.size() - 1 ? "\\n" : " ");
        
    
    return 0;

中档题-5 LIS (20 分)

链接
dfs:2分

#include <bits/stdc++.h>

using namespace std;
#define ll long long
int A[4000 + 10], B[800000 + 10];
int ans;
map<int, int> pot;
int num[800000 + 10], sum[800000 + 10];
void dfs(int pos, int n, int pre, int cnt)

	//pos:第pos个位置
    //n:一共n个数
    //pre:当前序列的最后一个数是pre
    if (pos > n)
    
        ans = max(cnt, ans);
        return;
    
    if (B[pos] == pre)
    
        dfs(pos + 1, n, pre, cnt + 1);
    
    else if (B[pos] < pre)
    
        dfs(pos + 1, n, pre, cnt);
    
    else
    
        dfs(pos + 1, n, pre, cnt);
        dfs(pos + 1, n, B[pos], cnt + 1);
    


int main(int argc, char *argv[])

    int n, m, i, j;
    cin >> n >> m;
    for (j = 1; j <= n; j++)
    
        scanf("%d", &A[j]);
        pot[A[j]] = j;
    
    for (i = 1; i <= m; i++)
    
        scanf("%d", &B[i]);
        B[i] = pot[B[i]];
    
    dfs(1,m,0,0);
    cout << ans << endl;
    return 0;


dfs剪枝后:8分

#include <bits/stdc++.h>

using namespace std;
#define ll long long
int A[4000 + 10], B[800000 + 10];
int ans;
map<int, int> pot;
int num[800000 + 10],sum[800000 + 10];
void dfs(int pos, int n, int pre, int cnt)

    //pos:第pos个位置
    //n:一共n个数
    //pre:当前序列的最后一个数是pre
    //cnt:当前序列的个数
    //num[pos],sum[pos]:前面有sum[pos]个,最后一个数是num[pos]
	if (pos > n)
	
		ans = max(ans, cnt);
		return;
	
    if(num[pos]==0)
        num[pos]=pre;
        sum[pos]=cnt;
    
    else if(cnt>sum[pos]&&pre<=num[pos])
        sum[pos]=cnt;
        num[pos]=pre;
    else if(cnt<sum[pos]&&pre>=num[pos])
        return ;
    
	if (pre > B[pos])
		dfs(pos + 1, n, pre, cnt);
	else if (B[pos] == pre)
	
		dfs(pos + 1, n, B[pos], cnt + 1);
	
	else
	
		dfs(pos + 1, n, pre, cnt);
		dfs(pos + 1, n, B[pos], cnt + 1);
	


int main(int argc, char *argv[])

	int n, m, i, j;
	cin >> n >> m;
	for (j = 1; j <= n; j++)
	
		scanf("%d", &A[j]);
		pot[A[j]] = j;
	
	for (i = 1; i <= m; i++)
	
		scanf("%d", &B[i]);
		B[i] = pot[B[i]];
	
	dfs(1, m, 0, 0);
	cout << ans << endl;
	return 0;


中档题-6 勋总的求偶日记 (25 分)

链接
dfs:10分

// O(n)
#include <bits/stdc++.h>

using namespace std;
#define ll long long
int num[100];
ll mod = 1e9 + 7;
ll dp[100][100];
ll dfs(int pos, int limit, ll cnt)

    //pos:第pos位数
    //limit :上界,1上界,0非上界
    if (pos == -1)
    
        return max(cnt, 1LL);
    
    int n;
    if (limit == 1)
        n = num[pos];
    else
        n = 1;
    ll ans = 1;
    for (int i = 0; i <= n; i++)
    
        if (i == 0)
            ans *= dfs(pos - 1, limit && i == num[pos], cnt);
        else
            ans *= dfs(pos - 1, limit && i == num[pos], cnt + 1);
    
    return ans % mod;

void solve(ll x)

    int n = 0;
    do
    
        num[n++] = x % 2;
        x /= 2;
     while (x);
    printf("%lld\\n", dfs(n - 1, 1, 0));

int main(int argc, char *argv[])

    int T;
    ll n;
    cin >> T;
    while (T--)
    
        scanf("%lld", &n);
        solve(n);
    

    return 0;


dfs剪枝后(记忆化):25分

#include <bits/stdc++.h>

using namespace std;
#define ll long long
int num[100];
ll mod = 1e9 + 7;
ll dp[100][100];
//数位dp
ll dfs(int pos, int limit, ll cnt)

    //pos:第pos位数
    //limit :上界,1上界,0非上界
    if (pos == -1)
    
        return max(cnt, 1LL);
    
    int n;
    if (limit == 1)
        n = num[pos];
    else
        n = 1;
    ll ans = 1;
    if(limit==0)
        if(dp[pos][cnt]!=-1)return dp[pos][cnt];
    
    for (int i = 0; i <= n; i++)
    
        if (i == 0)
            ans *= dfs(pos - 1, limit && i == num[pos], cnt);
        else
            ans *= dfs(pos - 1, limit && i == num[pos], cnt + 1);
    
    ans%=mod;
    if(limit==0)
        dp[pos][cnt]=ans;
    
    return ans ;

void solve(ll x)

    int n = 0;
    do
    
        num[n++] = x % 2;
        x /= 2;
     while (x);
    printf("%lld\\n", dfs(n - 1, 1, 0));

int main(int argc, char *argv[])

    int T;
    ll n;
    cin >> T;
    memset(dp,-1,sizeof(dp));
    while (T--)
    
        scanf("%lld", &n);
        solve(n);
    

    return 0;

压轴题-1 贝贝的数组划分 (30 分)

链接
dfs:9分

#include <bits/stdc++.h>
using namespace std;
#define ll long long
ll num[20];
ll ans;
void dfs(int pos, int k, int n, ll t, ll sum)

    //pos:第pos个数
    //k:切k刀
    //n:一共n个数
    //t: 前面已切部分的按位与结果
    //sum: 上一刀的数到当前位置的数的总和
    if (pos >= n)
    
        if (k == 0)
        
            t &= sum;
            ans = max(ans, t);
        
        return;
    
    dfs(pos + 1, k, n, t, sum + num[pos]);
    dfs(pos + 1, k - 1, n, t & (sum + num[pos]), 0);

int main()


    int n, k, T;
    cin >> T;
    while (T--)
    
        cin >> n >> k;
        for (int i = 0; i < n; i++)
        
            cin >> num[i];
        
        ans = 0;
        dfs(0, k - 1, n, (1LL << 60) - 1, 0);
        cout<<ans<<endl;
    

    return 0;


dfs剪枝后:15分

#include <bits/stdc++.h>
using namespace std;
#define ll long long
ll num[20];
ll ans;
void dfs(int pos, int k, int n, ll t, ll sum)

    //pos:第pos个数
    //k:切k刀
    //n:一共n个数
    //t: 前面已切部分的按位与结果
    //sum: 上一刀的数到当前位置的数的总和
    if(t<=ans||k<0)return ;
    if (pos >= n)
    
        if (k == 0)
        
            t &= sum;
            ans = max(ans, t);
        
        return;
    
    dfs(pos + 1, k, n, t, sum + num[pos]);
    dfs(pos + 1, k - 1, n, t & (sum + num[pos]), 0);

int main()


    int n, k, T;
    cin >> T;
    while (T--)
    
        cin >> n >> k;
        for (int i = 0; i < n; i++)
        
            cin >> num[i];
        
        ans = 0;
        dfs(0, k - 1, n, (1LL << 60) - 1, 0);
        cout<<ans<<endl;
    

    return 0;

压轴题-2 别装13 (30 分)

链接
dfs:10分

#include <bits/stdc++.h>
using namespace std;
const int SIZE = 100000 + 10;
vector<int> g基本算法——深度优先搜索(DFS)和广度优先搜索(BFS)

深度优先搜索算法解释下?

Python算法-深度优先搜索&广度优先搜索(DFS&BFS)

图的广度、深度优先搜索和拓扑排序

图的遍历之 深度优先搜索和广度优先搜索

深度优先搜索和广度优先搜索、A星算法三种算法的区别和联系?