DFS专题

题单地址:【237题】算法基础精选题单_ACM竞赛_ACM/CSP/ICPC/CCPC/比赛经验/题解/资讯_牛客竞赛OJ_牛客网

老子的全排列呢

dfs+回溯

int n = 8;
int idx;
int record[10];
bool vis[10];void dfs(int num)
{if(num==n){for(int i=1;i<=n;i++) cout<<record[i]<<" ";cout<<endl;return ;}for(int i=1;i<=n;i++){if(!vis[i]){vis[i] = true;record[++idx] = i;dfs(num+1);record[idx--] = 0;vis[i] = false;}}}

N皇后问题

O(n!)

 借用一位博主的图说明x+y和x-y+n的

const int N = 15*2;
int n,ans;
int col[N],dig[N],undig[N];void dfs(int u)//u代表行数
{if(u == n){//已经搜索了n行ans++;return ;}for(int y=0;y<n;y++){if(!col[y] && !dig[u+y] && !undig[u-y+n]){col[y] = dig[u+y]  = undig[u-y+n] = true;dfs(u+1);col[y] = dig[u+y]  = undig[u-y+n] = false;}}
}void solve()
{cin>>n;dfs(0);cout<<ans<<endl;
}

O(2^(n*n))

TLE的写法,想想就可怕

const int N = 15*2;
int n,ans;
int col[N],row[N],dig[N],undig[N];void dfs(int x,int y,int u)
{if(y==n){x++;y=0;}if(x==n){if(u==n) ans++;return;}//不放dfs(x,y+1,u);//放if(!col[y]&&!row[x]&&!dig[x-y+n]&&!undig[x+y]){col[y] = row[x] = dig[x-y+n] = undig[x+y] = true;dfs(x,y+1,u+1);col[y] = row[x] = dig[x-y+n] = undig[x+y] = false;}}void solve()
{cin>>n;dfs(0,0,0);cout<<ans<<endl;
}

马踏棋盘

走迷宫的写法,和迷宫的上下左右稍有不同,深搜时注意别越界且前往的点上没走过即可

#define PII pair<int,int>
const int N = 15+2;
int n,m;
const PII dir[4] = {{1,2},{2,1},{-1,2},{-2,1}};
bool vis[N][N];
int ans;bool in(int x,int y)
{return (x>=1 && x<=n && y>=1 && y<=m);
}void dfs(int x,int y)
{if(x==n && y==m){ans++;return;}for(int i=0;i<4;i++){int tx = dir[i].first+x;int ty = dir[i].second+y;if(in(tx,ty) && !vis[tx][ty]){vis[tx][ty] = true;dfs(tx,ty);vis[tx][ty] = false;}}
}void solve()
{cin>>n>>m;vis[1][1] = true;dfs(1,1);cout<<ans<<endl;
}

数独挑战

dfs+剪枝,棋盘格子看起来很多觉得会TLE,实际上考虑上数独的规则进行剪枝还是可以过的。

分为三部分记录棋盘信息:行、列、块,块分为

 11 |  12 | 13

 21 |  22 | 23

 31 |  32 | 33

一共九个部分,(x,y)在某一块可以用[x/3][y/3]来确定位置

其余的部分和常规dfs相差无几,注意的是回溯的时候不能都置为0,只有你自己填的数可以删掉,题目原来给的数不能删,所以要额外开一个origin数组记录哪些位置是一开始就有数的

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define fasten cin.tie(0),cout.tie(0);ios::sync_with_stdio(false)const int N = 10+2;
int g[N][N];
bool row[N][10];//第i行的1-9各有几个
bool col[N][10];
bool block[4][4][10];//左上角的块为1,1 依次为1,2 1,3 ... 
int blank = 81;//待填的空格
int origin[N][N];//记录原始给定的数字,回溯时不能删除
void print(){for(int i=0;i<9;i++){for(int j=0;j<9;j++){cout<<g[i][j]<<" ";}cout<<endl;}
}
void dfs(int x,int y)
{if(y==9){y = 0;x++; }if(blank==0){print();return ;}if(g[x][y]!=0) dfs(x,y+1);bool flag = false;//记录该格子是否还能填数,不能的话该搜索路径不用搜索下去了for(int i=1;i<=9;i++){if(!block[x/3][y/3][i] && !row[x][i] && !col[y][i]){flag = true;g[x][y] = i;block[x/3][y/3][i] = row[x][i] = col[y][i] = true;blank--;dfs(x,y+1);blank++;//若是自己填的数就回溯为0,系统给定的数不能改动if(origin[x][y]) g[x][y] =origin[x][y];else g[x][y] = 0;block[x/3][y/3][i] = row[x][i] = col[y][i] = false;}}if(!flag) return ;}
void solve()
{for(int i=0;i<9;i++){for(int j=0;j<9;j++){cin>>g[i][j];origin[i][j] = g[i][j];if(g[i][j]!=0){int e = g[i][j];blank--;row[i][e] = true;col[j][e] = true;block[i/3][j/3][e] = true;}}}//debug// for(int i=1;i<=9;i++) cout<<i<<" ";// cout<<endl;// for(int i=0;i<3;i++){//     for(int k=0;k<3;k++){//         for(int j=1;j<=9;j++){//             cout<<block[i][k][j]<<" ";//         }//         cout<<endl;//     }// }dfs(0,0);}
signed main()
{fasten;
//     freopen("stdin.txt","r",stdin);
//     freopen("stdout.txt","w",stdout);solve();return 0;
}

幸运数字Ⅱ

可以先用dfs把所有只含4or7且<=1e9的数处理出来放在一个容器内,然后再[l,r]内使用二分计算总和,用string比用long long快大约100倍左右

#define PII pair<int,int>
#define ll long long
vector<ll>v;void dfs(string s,int digit)
{if(digit>9){return ;}int tmp = 0;for(int i=0;i<s.length();i++){tmp = tmp*10+(s[i]-'0');}if(tmp<1e9){if(tmp!=0) v.push_back(tmp);dfs("4"+s,digit+1);dfs("7"+s,digit+1);}
}void solve()
{dfs("",0);v.push_back(4444444444);sort(v.begin(),v.end());// for(auto it:v){// 	cout<<it<<endl;// }long long l,r;cin>>l>>r;long long res = 0;for(ll i=l;i<=r;){auto it = lower_bound(v.begin(),v.end(),i);res += min(r-i+1ll,(*it-i+1ll))*(*it);i = *it+1;}cout<<res<<endl;
}

[NOIP2017]奶酪

回溯dfs写法会超时,别写回溯写法

有的题目一定要回溯,但是有的题目不用回溯,选择不回溯可以优化算法

那什么时候不需要回溯?

当遇到一个选择时,一定要对它操作时,那么就不需要回溯。比如要标记求所有情况,找到了就要标记。如果取消标记,那么就会重复计算。在这道题中,小鼠尝试通过空洞从起点到终点,到达一个点时,小鼠需要知道该点范围内的可到达的点中有没有能到达终点的点,如果有的点不能到达终点,就不必再走那个点了。

如何知道该点能不能达到终点?

dfs搜索时会直接搜索到最深处,接着从底层一层一层往上反馈该点能不能通往终点。该点若已经搜索过,必定打上了标记(回溯则会把该标记划去,那就需要重复搜索了)

AC版本

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define int long long
#define fasten cin.tie(0),cout.tie(0);ios::sync_with_stdio(false)const int N = 1000+2;
int n;
int h,r;
bool vis[N];//记录该空洞有没有走过
bool g[N][N];
int x[N],y[N],z[N];
bool isfind = false;bool dfs(int i)
{if(z[i]+r>=h){return true;}if(vis[i]) return false;vis[i] = true;for(int j=0;j<n;j++){if(g[i][j] && dfs(j)) return true;}return false;
}void solve()
{int t;cin>>t;while(t--){memset(g,0,sizeof g);memset(vis,0,sizeof vis);cin>>n>>h>>r;for(int i=0;i<n;i++){cin>>x[i]>>y[i]>>z[i];}for(int i=0;i<n;i++){for(int j=0;j<n;j++){if(i!=j)g[i][j]=g[j][i]=(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])+(z[i]-z[j])*(z[i]-z[j]) <=4*r*r;}}for(int i=0;i<n;i++){if(z[i]<=r){if(dfs(i)){puts("Yes");isfind = true;break;}}}if(!isfind) puts("No");isfind = false;}
}
signed main()
{fasten;
//     freopen("stdin.txt","r",stdin);
//     freopen("stdout.txt","w",stdout);solve();return 0;
}

TLE版本

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define fasten cin.tie(0),cout.tie(0);ios::sync_with_stdio(false)class point
{
public:double x,y,z;point(){};point(int a,int b,int c){x=a,y=b,z=c;}
};double dist(point p1,point p2)
{double x = (p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y)+(p1.z-p2.z)*(p1.z-p2.z);return sqrt(x);
}
const int N = 1000+2;
point a[N];
int n;
double h,r;
bool vis[N];//记录该空洞有没有走过
bool g[N][N];
bool isfind = false;void dfs(int x,int y,int z,int idx)
{if(z+r>=h){isfind = true;return ;}for(int i=0;i<n;i++){point tmp(x,y,z);if(!vis[i] && g[idx][i]){vis[i] = true;dfs(a[i].x,a[i].y,a[i].z,i);vis[i] = false;}}}
void solve()
{int t;cin>>t;while(t--){memset(g,0,sizeof g);cin>>n>>h>>r;for(int i=0;i<n;i++){cin>>a[i].x>>a[i].y>>a[i].z;}for(int i=0;i<n;i++){for(int j=0;j<n;j++){if(i!=j)g[i][j] = dist(a[i],a[j])<=2*r;}}for(int i=0;i<n;i++){if(a[i].z<=r) dfs(a[i].x,a[i].y,a[i].z,i);}if(isfind) puts("Yes");else puts("No");isfind = false;}
}
signed main()
{fasten;
//     freopen("stdin.txt","r",stdin);
//     freopen("stdout.txt","w",stdout);solve();return 0;
}

wyh的迷宫

迷宫问题不在赘述

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define int long long
#define fasten cin.tie(0),cout.tie(0);ios::sync_with_stdio(false)
#define PII pair<int,int>
const int N = 500+2;
int n,m;
const PII dir[4] = {{0,1},{1,0},{-1,0},{0,-1}};
bool vis[N][N];
string s[N];
PII _begin,_end;
bool isfind = false;bool in(int x,int y)
{return (x>=1 && x<=n && y>=1 && y<=m);
}void dfs(int x,int y)
{//cout<<x<<" "<<y<<endl;if(x==_end.first && y==_end.second){isfind = true;return ;}for(int i=0;i<4;i++){int tx = dir[i].first+x;int ty = dir[i].second+y;if(in(tx,ty) && !vis[tx][ty] && s[tx][ty]!='x'){if(x==_end.first && y==_end.second){isfind = true;return ;}vis[tx][ty] = true;dfs(tx,ty);}}return ;
}void solve()
{int t;cin>>t;while(t--){memset(vis,0,sizeof vis);cin>>n>>m;for(int i=1;i<=n;i++) cin>>s[i],s[i]=" "+s[i];for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){if(s[i][j]=='s') _begin = {i,j};else if(s[i][j]=='t') _end = {i,j};}}vis[_begin.first][_begin.second] = true;dfs(_begin.first,_begin.second);if(isfind) cout<<"YES"<<endl;else cout<<"NO"<<endl;isfind = false;}
}signed main()
{fasten;
//     freopen("stdin.txt","r",stdin);
//     freopen("stdout.txt","w",stdout);solve();return 0;
}

Lake Counting

求连通分支的个数,可用并查集的知识

也可以直接搜索,标记访问过的点,查看有几块

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define int long long
#define fasten cin.tie(0),cout.tie(0);ios::sync_with_stdio(false)
#define PII pair<int,int>
const int N = 100+5;
char s[N][N];
int n,m;
int ans;
const PII dir[8] = {{1,0},{1,1},{1,-1},{0,1},{0,-1},{-1,1},{-1,0},{-1,-1}};bool in(int x,int y)
{return (x>=0 && x<n && y>=0 && y<m);
}void dfs(int x,int y)
{s[x][y] = '.';//走过的修改成陆地for(int i=0;i<8;i++){//八个方向都可走int tx = x+dir[i].first;int ty = y+dir[i].second;if(in(tx,ty) && s[tx][ty]=='W'){dfs(tx,ty);}}return ;
}
void solve()
{cin>>n>>m;for(int i=0;i<n;i++){for(int j=0;j<m;j++){cin>>s[i][j];}}for(int i=0;i<n;i++){for(int j=0;j<m;j++){if(s[i][j]=='W'){dfs(i,j);ans++;}}}cout<<ans<<endl;
}signed main()
{fasten;
//     freopen("stdin.txt","r",stdin);
//     freopen("stdout.txt","w",stdout);solve();return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/251210.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

HBase集群搭建

hbase 1.解压HBase安装包 先 下载HBase压缩包&#xff0c;并解压安装文件&#xff0c;示例代码如下&#xff1a; tar -zxvf hbase-2.0.1-bin.tar.gz2. 修改配置文件 编辑 conf目录下的 hbase-env.sh文件&#xff0c;示例代码如下&#xff1a; cd conf vi hbase-env.sh添加…

滴滴出行怎么下载丨办法总比困难多

滴滴打车出行端下载一&#xff1a;登陆自己的商店&#xff0c;在已购买项目里面直接搜索“滴滴车主”就可以下载了。当然如果你之前没下载过的话&#xff0c;那也是搜索不到的。 滴滴出行下载二&#xff1a;在某信中找到《 千米应用 》订阅号获取到应用安装途径后按要求选择对…

PHP微信支付之扫码支付

在手机微信端进行微信支付&#xff0c;直接调起JSAPI支付&#xff0c;这可以实现在微信里边的开的页面进行支付&#xff0c;比如微商城&#xff0c;微信端JSAPI支付详见&#xff1a;PHP实现微信支付(jsapi支付)和退款(无需集成支付SDK)&#xff1b;但有时候商城还有PC端&#x…

【微信小程序付款转二维码付款】

需要的参数&#xff1a;session_id, timeStamp, nonceStr, package, paySign, appid,uuid session_id是协议获取 timeStamp, nonceStr, package, paySign, appid是订单数据 uuid是调用接口获取 第一步要获取小程序的sessionId 基于pc协议不风控 获取订单数据timeStamp, nonceS…

您的滴滴2020年度出行报告,请查收!

桔妹导读&#xff1a;滴滴2020年度出行盘点新鲜出炉&#xff0c;每个人都有属于自己的滴滴之城&#xff0c;快来看看你的城。打玉人、Tony的亲人、最该呵护的人……这12种有趣的灵魂&#xff0c;你是哪一种&#xff1f; 一年一度的个人出行盘点新鲜出炉 你的最晚一单 是不是还是…

微信支付接口详细步骤

对接微信支付接口-详细步骤教程-你不知道的那些坑TOC 近期公司项目需要对接微信支付宝等支付接口,然后就看官网看文档查百度,我这里只说对接微信支付接口,下一篇说微信退款. 先登录微信官网查看文档 这里我先解释一下微信支付接口的步骤 第一步:统一下单 (此操作是我们对接微…

滴滴出行用户运营分析

一、功能模块 滴滴出行APP功能模块主要分为五个部分&#xff0c;包含提供服务的类别、安全中心、用户中心、首页推送及功能类按键。 1.服务类别 此模块列出了滴滴出行所能提供的各种服务&#xff0c;包括一系列出行用车服务、公交线路查询、二手车买卖以及金融服务&#xff0c;…

滴滴出行app——网约车出行的背后(上)

互联网出行已经撬动千亿级市场规模&#xff0c;而滴滴出行作为最大的出行平台&#xff0c;占领着网约车市场的最大份额。本文将从市场、用户、功能、运营等方面对滴滴出行进行分析。 关于滴滴 一、功能框架与使用流程 二、市场分析 三、用户分析 四、功能分析 五、运营分析 六…

企业付款到零钱API开发~~~ 付款到微信

近日&#xff0c;在开发“微信企业付款到零钱”的功能。之前有过微信开发的经验&#xff0c;但是第一次接触“付款到零钱“这一块的业务&#xff0c;查询了很多的博客资料以及走了很多的弯路。也发现“企业付款到零钱”分享的博客并不多。特地写了该博客&#xff0c;希望对你们…

滴滴出行平台业务架构演进

桔妹导读&#xff1a;为了满足不同用户在价格、体验等方面的差异化诉求&#xff0c;滴滴提供了越来越丰富的品类&#xff0c;这些品类大体流程是类似的&#xff0c;在一些细节体验上有差异&#xff0c;一套架构如何兼顾隔离和复用&#xff0c;同时支持这些品类&#xff0c;且看…

【第三章:存储系统】

目录 知识框架No.0 引言No.1 存储器概述一、存储器的层次结构二、储存器的分类1、按照层次结构进行分类2、按照存储介质3、按照存取方式4、信息的可更改性5、信息的可保存性 三、存储器的性能指标1、存储容量2、单位成本3、存储速度 No.2 主存储器的基本组成一、基本的半导体元…

数字后的顿号变成斜杠 - 解决方案

前言 PC端键盘输入数字后的顿号变成斜杠&#xff0c;这并不是因为Office的自动校正功能引起的&#xff0c;而是由搜狗输入法的智能调整数字后标点功能引起的&#xff0c;该功能也会将数字后的中文句号改为英文句号&#xff0c;若不需要这些功能&#xff0c;则可以关闭搜狗输入…

邓号用计算机怎么输入,电脑上顿号怎么打出来

【电脑上顿号怎么打出来】电脑最为重要的一个用途就是编辑文档&#xff0c;而文编文档就要涉及到符号&#xff0c;一般的句号、逗号键盘上都要。那么&#xff0c;顿号这类电脑键盘上没有的符号怎么打出来呢&#xff1f;很多人反映键盘上没有顿号的按键&#xff0c;使用时打不出…

在电脑上顿号咋打?

按照以下步骤可以打出顿号&#xff1a; 1、首先将输入法的中英文切换到中文&#xff0c;如图所圈出的位置&#xff1b; 2、在键盘上敲击下图所圈出的键&#xff0c;便可打出顿号。&#xff08;有的电脑敲击“\”按键哦&#xff01;&#xff09; 需注意的是&#xff0c;如果输入…

数据分割,顿号替换成制表符

有些时候我们需要向数据库里导入一些现有数据&#xff0c;而数据格式的清理则是很重要的一部分&#xff0c;本文就将存在顿号的数据串分割成一个一个的数据。 需要使用到的工具是&#xff1a;EditPlus

Office 顿号怎么输

中文状态下回车上面一个按键就是 转载于:https://www.cnblogs.com/acetaohai123/p/6589431.html

html中键盘分别对应的值,电脑键盘键值所对应的功能详解

虽然&#xff0c;电脑的键盘看上去很相似&#xff0c;但是&#xff0c;只要仔细观察&#xff0c;不同的电脑配置的键盘的键值还是有些许细微的差异。好在一些常用键值都是一样的&#xff0c;这里详解的就是这些通用键值所对应的功能。有兴趣的朋友可以参考一下哦&#xff01; E…

关于CentOS系统中键盘错乱的解决window10默认输入法顿号句号失灵

关于CentOS系统中键盘错乱的解决 首先&#xff1a;我的CentOS是装在windows系统的虚拟机中。 错误如图&#xff1a; 在网上查了很多解决办法&#xff0c;然而不太行 首先&#xff0c;可以使用localectl status查看&#xff0c;正常如下 如果不对则修改&#xff1a; System Lo…

搜狗拼音linux 知乎,搜狗拼音知乎专版下载

搜狗拼音输入法知乎专版是知乎和搜狗联合发布的「刘看山定制版输入法」&#xff0c;内置刘看山动态皮肤&#xff0c;当输入情景关键词的时候&#xff0c;还会有可爱的刘看山系列表情。而在功能上也更贴近了知乎用户的使用习惯&#xff0c;包括直角引号「」的快捷输入&#xff0…

微信小黄鸡php,微信表情包小黄鸡含义

这是微信表情包小黄鸡含义下载&#xff0c;微信表情包小黄鸡含义小黄鸡高登表情包是一款小黄鸡系列又一给力大作&#xff0c;撩人的表情再搭配污污的标语&#xff0c;想必对女生朋友杀伤力巨大&#xff0c;非常适合情人节撩妹所用&#xff0c;内含的动画图片&#xff0c;丰富的…