草庐IT

【DFS专题】深度优先搜索 “暴搜”优质题单推荐 10道题(C++ | 洛谷 | acwing)

CPT1024 2023-07-17 原文

文章目录

【DFS专题】优质题单推荐 10道题(C++ | 洛谷 | acwing)

题单

一、模板 [极为重要]

全排列DFS

  • 每个位置选什么数
#include<iostream>
using namespace std;
const int N = 10;
int path[N];//保存序列
int state[N];//数字是否被用过
int n;
void dfs(int u)
{
    if(u > n)//数字填完了,输出
    {
        for(int i = 1; i <= n; i++)//输出方案
            cout << path[i] << " ";
        cout << endl;
    }

    for(int i = 1; i <= n; i++)//空位上可以选择的数字为:1 ~ n
    {
        if(!state[i])//如果数字 i 没有被用过
        {
            path[u] = i;//放入空位
            state[i] = 1;//数字被用,修改状态
            dfs(u + 1);//填下一个位
            state[i] = 0;//回溯,取出 i
        }
    }
}

int main() {
    cin >> n;
    dfs(1);
}

组合型DFS

  • 与全排列的差别就是第二个for循环开始的位置,换句话说就是每个数该放什么位置。
#include <bits/stdc++.h>
using namespace std;
const int N = 30;
int path[N];
int n, m;

void dfs (int u, int start ) {//u:层数  start:起始的数值
    if (u > m) {
        for (int i = 1; i <= m; i ++ ) {
            cout << path[i] << ' ';
        }
        puts("");
    }
    else {
        for (int i = start; i <= n; i ++) {//
            path[u] = i;//表示已经填了
            dfs(u + 1, i + 1);//递归下一层
            path[u] = 0;//恢复现场
        }
    }
} 

int main () {
    cin >> n >> m;
    dfs(1,1); //第一层开始  且从1开始枚举
    return 0;
}

指数DFS

  • 参数 : 前u个数 选 or 不选 的
  • 需要保存第x位置的状态的时候就需要用st数组来存状态
  • int st[] 0:没有遇见 1 选 2不选
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 16;
int st[N]; 
int n;
void dfs (int u) {//u :层数
  if (u > n) {//叶子结点
    for (int i = 1; i <=n; i ++ ){
      if (st[i] == 1) {//如果选了 就输出 1选 2不选
        cout << i << ' ';
      }
    }
    puts("");
    return ;
  }
 
  st [u] = 1;//选
  dfs (u + 1);//递归下一层
  st[u] = 0;//回溯
  
   st[u] = 2;//不选
  dfs (u+1);//递归下一层
  st[u] = 0;//回溯 【恢复现场】 
}
int main () {
  cin >> n;
  dfs(1);
  return 0;
}

二、专题

烤鸡 (指数BFS)

  • 每个方案有3种选择,枚举全部则有 310 种方案数

    https://www.luogu.com.cn/problem/P2089
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 20;
int n;
int arr[N]; // 存储临时答案
int res = 0;// 方案数量
int mem[60000][N]; // 存储总方案数
// 60000 >= 3^10 (最多枚举数量)

// x : 当前枚举到哪个数  sum : 当前总和
void dfs(int x, int sum ) {
    if(sum > n) return ;// 剪枝
    if(x > 10) {
        if(sum == n) {
            res ++;
            for(int i = 1; i <= 10; i ++) {
                mem[res][i] = arr[i];
            }
        }
        return;
    }
    
    for(int i = 1; i <= 3; i ++) {
        arr[x] = i;
        dfs(x + 1, sum + i);
        arr[x] = 0; // 恢复现场
    }
}

int main () {
    cin >> n;
    dfs(1, 0);
    printf("%d\n" , res);
    for (int i = 1; i <= res; i ++ ) {
        for(int j = 1; j <= 10; j ++) {
            printf("%d ", mem[i][j]);
        }
        printf("\n");
    }
    return 0;
}

P1088 火星人 【全排列】

  • https://www.luogu.com.cn/problem/P1088

  • 为什么要 m + 1

#include <iostream>  
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 10010;
int n, m;
int res = 0;
int ans[N], a[N];
bool st[N];
bool flag = false;
void dfs(int x) {
    if(flag) return; //剪枝  因为只会输出一次结果
    
    if(x > n) {
        res ++;
        if(res == m + 1) {
            for(int i = 1; i <= n; i ++ ){
                printf("%d ", ans[i]);
            }
            flag =true;
        }
        return ;
    }
    for (int i = 1; i <= n; i ++ ){
        if(!res) {
            i = a[x]; // 起点
        }
        if(! st[i]) {
            st[i] = true;
            ans[x] = i;
            dfs(x + 1);
            ans[x] = 0;
            st[i] = false;
        }
    }
}

int main () {
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i ++ ) scanf("%d", &a[i]);;
    dfs(1);
    return 0;
}

P1149 火彩棒 [预处理 ]

https://www.luogu.com.cn/problem/P1149

  • 思路一 、 模拟
  • 思路二 :预处理 + dfs 枚举

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 100010;

int n;
int res = 0;
int s[N];
int  num[N] = {6,2,5,5,4,5,6,3,7,6};

void dfs(int x, int sum) {
    if(sum > n ) return ;
    if(x > 3) {
       if(s[1] + s[2] == s[3] && sum == n) {
           res ++;
       }
       return ;
    }
   //枚举前 1000
   for(int i = 0; i <= 1000; i ++) {
       s[x] = i;
       dfs(x + 1, sum + num[i]) ;
       s[x] = 0;
   } 
}

int main () {
    scanf("%d", &n);
    n -= 4;
	//递推求前1000个数
    for (int i = 10; i <= 1000; i ++ ) {
        num[i] = num[i % 10] + num[i / 10];
    }
    dfs(1, 0);
    printf("%d\n" , res);
    return 0;
}

P2036 PERKET

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 20;

int n;
int res = 1e9;
int s[N], k[N];
int st[N]; // 0 表示没考虑 1 选  2 不选

void dfs(int x) {
    if(x > n) {
        bool first = false; // 如果没选就不计算res
        int sum1 = 1;//酸的积
        int sum2 = 0; // 苦的和
        for (int i = 1; i <= n; i ++ ) {
            if(st[i] == 1) {
                sum1 *= s[i];
                sum2 += k[i];
                first = true;
            }
        }
        if(first) {
            res = min(res, abs(sum1 - sum2));
        }
        return ;
    }
    
    st[x] = 1;
    dfs(x + 1);
    st[x] = 0;
    
    st[x] = 2;
    dfs(x + 1);
    st[x] = 0;
}

int main () {
    scanf("%d", &n);
    for (int i = 1; i <= n; i ++ ) scanf("%d%d", &s[i], &k[i]);;
    dfs(1);
    printf("%d\n" , res);
    return 0;
}

P1135 奇怪的电梯 暴力

Ki 的值 表示 上 or 下 的层数

  • 学个思路就可以

P1036 [NOIP2002 普及组] 选数 (组合)

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 30;

int n, k;
int a[N], q[N];
int res = 0;

//判断是否为素数
bool is_prime(int x) {
    if(x < 2) return false;
    for(int i = 2; i <= x / i; i ++) { // 从2开始呀
        if(x % i == 0) return false; 
    }
    return true;
}

void dfs(int x, int start) {
    if(x > k) {
        int sum = 0;
        for(int i = 1; i <= k; i ++) {
            sum += a[i];
        }   
        if(is_prime(sum)) {
            res ++;
        }
        return;
    }
    
    for(int i = start; i <= n; i ++) {
        a[x] = q[i];
        dfs(x + 1, i + 1);
        a[x] = 0;
    }
}

int main () {
    cin >> n >> k;
    for (int i = 1; i <= n; i ++ ) cin >> q[i];
    dfs(1, 1);
    cout << res << endl;
    return 0;
}

P1596 [USACO10OCT]Lake Counting S 【DFS求图的连通块】

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 110;

int n, m;
char g[N][N];
bool st[N][N];
int res = 0;

int dx[8] = {1,1,1,0,0,-1,-1,-1};
int dy[8] = {-1,0,1,1,-1,1,0,-1};


void dfs(int x, int y) {
    for(int i = 0; i < 8; i ++) {
        int a = x + dx[i], b = y + dy[i];
        if(a < 0 || a >= n || b < 0 || b >= m) continue; // 越界
        if(g[a][b] != 'W' ) continue; // 不是山
        if(st[a][b]) continue; //来过
        st[a][b] = true;
        dfs(a, b);
    }
}

int main () {
    cin >> n >> m;
    for(int i = 0; i < n; i ++) cin >> g[i];
    for (int i = 0; i < n; i ++ ) {
        for (int j = 0; j < m; j ++ ) {
            if(g[i][j] == 'W' && !st[i][j]) {
                dfs(i, j);
                res ++;
            }
            // cout << g[i][j] << ' ';
        }
        // cout << endl;
    }
    cout << res << endl;
    return 0;
}

八数码

  • https://www.acwing.com/problem/content/1116/ 棋盘题

tijie : https://www.acwing.com/solution/content/133704/

小猫爬山

题目链接


#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;
const int N = 40;
int c[N], cab[N], n , w, ans ;

bool cmp (int a, int b){
    return a > b;
}

void dfs(int u, int cnt) {
    if(cnt >= ans) return ;
    if(u == n + 1) { // 遍历完每只小猫后  更新答案 !
        ans = min (ans, cnt);
        return;
    }
    
    for(int i = 1; i <= cnt; i ++) { // 遍历已经分配的车子  看看有没有合适的
        if(c[u] + cab[i] <= w) {
            cab[i] += c[u];
            dfs(u + 1, cnt);
            cab[i] -= c[u];
        }             
        
    }   
    cab[cnt + 1] = c[u]; // 没有合适的情况 就需要多加一个车子
        dfs(u + 1, cnt + 1);
        cab[cnt + 1] = 0;
    
}

int main () {
    cin >> n >> w;
    for(int i = 1; i <= n; i ++) cin >> c[i];
    ans = n;
    sort(c + 1, c + 1 + n, cmp); 
    dfs(1, 1);
    cout << ans << endl;
    return 0;
}

有关【DFS专题】深度优先搜索 “暴搜”优质题单推荐 10道题(C++ | 洛谷 | acwing)的更多相关文章

  1. 深度学习部署:Windows安装pycocotools报错解决方法 - 2

    深度学习部署:Windows安装pycocotools报错解决方法1.pycocotools库的简介2.pycocotools安装的坑3.解决办法更多Ai资讯:公主号AiCharm本系列是作者在跑一些深度学习实例时,遇到的各种各样的问题及解决办法,希望能够帮助到大家。ERROR:Commanderroredoutwithexitstatus1:'D:\Anaconda3\python.exe'-u-c'importsys,setuptools,tokenize;sys.argv[0]='"'"'C:\\Users\\46653\\AppData\\Local\\Temp\\pip-instal

  2. 由于 libgmp.10.dylib 的问题,Ruby 2.2.0 无法运行 - 2

    我刚刚安装了带有RVM的Ruby2.2.0,并尝试使用它得到了这个:$rvmuse2.2.0--defaultUsing/Users/brandon/.rvm/gems/ruby-2.2.0dyld:Librarynotloaded:/usr/local/lib/libgmp.10.dylibReferencedfrom:/Users/brandon/.rvm/rubies/ruby-2.2.0/bin/rubyReason:Incompatiblelibraryversion:rubyrequiresversion13.0.0orlater,butlibgmp.10.dylibpro

  3. ruby - ri 有空文件 – Ubuntu 11.10, Ruby 1.9 - 2

    我正在运行Ubuntu11.10并像这样安装Ruby1.9:$sudoapt-getinstallruby1.9rubygems一切都运行良好,但ri似乎有空文档。ri告诉我文档是空的,我必须安装它们。我执行此操作是因为我读到它会有所帮助:$rdoc--all--ri现在,当我尝试打开任何文档时:$riArrayNothingknownaboutArray我搜索的其他所有内容都是一样的。 最佳答案 这个呢?apt-getinstallri1.8编辑或者试试这个:(非rvm)geminstallrdocrdoc-datardoc-da

  4. ruby-on-rails - gem install rmagick -v 2.13.1 错误 Failed to build gem native extension on Mac OS 10.9.1 - 2

    我已经通过提供MagickWand.h的路径尝试了一切,我安装了命令工具。谁能帮帮我?$geminstallrmagick-v2.13.1Buildingnativeextensions.Thiscouldtakeawhile...ERROR:Errorinstallingrmagick:ERROR:Failedtobuildgemnativeextension./Users/ghazanfarali/.rvm/rubies/ruby-1.8.7-p357/bin/rubyextconf.rbcheckingforRubyversion>=1.8.5...yescheckingfor/

  5. ruby - 安装 tiny_tds 在 mac os 10.10.5 上出现错误 - 2

    我正在使用macos,我想使用ruby​​驱动程序连接到sqlserver。我想使用tiny_tds,但它给出了缺少free_tds的错误,但它已经安装了。怎么能过这个?~brewinstallfreetdsWarning:freetds-0.91.112alreadyinstalled~sudogeminstalltiny_tdsBuildingnativeextensions.Thiscouldtakeawhile...ERROR:Errorinstallingtiny_tds:ERROR:Failedtobuildgemnativeextension.完整日志如下:/System

  6. ruby - rails 3.2.2(或 3.2.1)+ Postgresql 9.1.3 + Ubuntu 11.10 连接错误 - 2

    我正在使用PostgreSQL9.1.3(x86_64-pc-linux-gnu上的PostgreSQL9.1.3,由gcc-4.6.real(Ubuntu/Linaro4.6.1-9ubuntu3)4.6.1,64位编译)和在ubuntu11.10上运行3.2.2或3.2.1。现在,我可以使用以下命令连接PostgreSQLsupostgres输入密码我可以看到postgres=#我将以下详细信息放在我的config/database.yml中并执行“railsdb”,它工作正常。开发:adapter:postgresqlencoding:utf8reconnect:falsedat

  7. ruby-on-rails - 在 osx 10.9.3 上使用 RVM 安装 ruby​​-1.9.3-p547 时出错 - 2

    如何解决这个错误:$rvminstall1.9.3Searchingforbinaryrubies,thismighttakesometime.Nobinaryrubiesavailablefor:osx/10.9/x86_64/ruby-1.9.3-p547.Continuingwithcompilation.Pleaseread'rvmhelpmount'togetmoreinformationonbinaryrubies.Checkingrequirementsforosx.Certificatesin'/usr/local/etc/openssl/cert.pem'arealr

  8. 深度学习12. CNN经典网络 VGG16 - 2

    深度学习12.CNN经典网络VGG16一、简介1.VGG来源2.VGG分类3.不同模型的参数数量4.3x3卷积核的好处5.关于学习率调度6.批归一化二、VGG16层分析1.层划分2.参数展开过程图解3.参数传递示例4.VGG16各层参数数量三、代码分析1.VGG16模型定义2.训练3.测试一、简介1.VGG来源VGG(VisualGeometryGroup)是一个视觉几何组在2014年提出的深度卷积神经网络架构。VGG在2014年ImageNet图像分类竞赛亚军,定位竞赛冠军;VGG网络采用连续的小卷积核(3x3)和池化层构建深度神经网络,网络深度可以达到16层或19层,其中VGG16和VGG

  9. u盘安装系统(win10为例) - 2

    下载微PE工具箱进入官网下载微PE工具箱-下载 安装好后,打开微PE工具箱客户端,选择安装PE到U盘 PE壁纸可选择自己喜欢的壁纸,勾选上包含DOS工具箱,个性化盘符图标 下载原版系统进入网站下载镜像NEXT,ITELLYOU如果没有账号,注册一下就好进入选择开始使用选择win10 这里我们选择消费者版,用迅雷把BT种子下载下来 下面的两个盘符,是PE工具箱安装进U盘后,分成的盘符,注意EFI的盘符,这里面不能删东西,也不能添东西,另一个盘符可以当做正常的U盘空间使用,我们现在需要把下载下来的景象文件复制到正常的U盘空间中去 这个时候我们的系统U盘就只做好了 安装系统我们将U盘插入电脑,开机,

  10. ruby-on-rails - OSX 10.7.5 - Ruby on Rails LoadError : Could not open library 'sodium' : dlopen(sodium, 5) - 2

    输入rakedb:create后我得到:LoadError:Couldnotopenlibrary'sodium':dlopen(sodium,5):imagenotfound.Couldnotopenlibrary'libsodium.dylib':dlopen(libsodium.dylib,5):imagenotfound这里还有一些输出。/Users/Mao/.rvm/gems/ruby-2.0.0-p451/gems/ffi-1.9.3/lib/ffi/library.rb:133:in`blockinffi_lib'/Users/Mao/.rvm/gems/ruby-2.0

随机推荐