DFS回溯-经典全排列问题(力扣)

前言

对于全排列问题,常用的做法是设置一个vis数组来确定位置i上的数字是否被访问,因为是全排列问题,所以不同的顺序也是不一样的排列,因此每次都是从起点开始询问**(注意起点到底是0还是1)**

46全排列(最简单的模板)

class Solution {
public:
    vector<int>v;//存储一个排列
   vector<vector<int>>ans;//答案
    int vis[10];
    void dfs(vector<int> & nums){
        int n = nums.size();
       
        if(v.size() == n){
            ans.push_back(v);
            return;
        }
        for(int i = 0; i < n; i++){
            if(vis[i])continue;
            vis[i] = 1;
            v.push_back(nums[i]);
            dfs(nums);
            v.pop_back();
            vis[i] = 0;
        }
        
    }
    
    vector<vector<int>> permute(vector<int>& nums) {
        dfs(nums);
        return ans;
    }

};

解题思路

相比于全排列1,全排列2增加了重复数字,但要求不能出现重复的排列。例如原始序列1 2 1 那么全排列里 1 1 2 和 1 1 2 (两个序列的两个1位置互换了),仍然当一种排列。最好的办法就是对其进行剪枝

  if(i > 0 && nums[i] == nums[i - 1] && vis[i - 1] == 0) continue;//树层去重

借鉴卡哥的一幅图,给大家看一下
在这里插入图片描述

(类似题目)P8605 [蓝桥杯 2013 国 AC] 网络寻路

#include<iostream>
#include<algorithm>
#include<string>
#include<vector>
#include<stack>
#include<cstdio>
#define rep(i,a,n) for(int i = a; i <= n; i++) 
#define per(i,a,n) for(int i = n; i >= a; i--)
 
using namespace std;
 
typedef long long ll;
 
const int N = 10010;
vector<int> v[N];
int vis[N];
int n,m;
ll ans;
vector<int>st;
void dfs(int x){
	int n = v[x].size();
	if(st.size() == 3){//因为终点位置可以和起点相同,所以当路径元素为3个的时候,就开始特判 
		rep(i,0, n - 1){
			int tp = v[x][i];
			if(!vis[tp] || tp == st[0]) ans++;//没被访问或者是起点 
		}
		return ;
	}
	
	rep(i,0,n-1){
		int tp = v[x][i];
		if(!vis[tp]){
			vis[tp] = 1;
			st.push_back(tp);
			dfs(tp);
			st.pop_back();
			vis[tp] = 0;
		}
	}
}

int main(){
	cin >> n >> m;
	int u,vv;
	rep(i,1,m){
		cin >> u >> vv;
		v[u].push_back(vv);
		v[vv].push_back(u);
	}
	rep(i,1,n){
		vis[i] = 1;
		st.push_back(i);
		dfs(i);
		vis[i] = 0;
		st.pop_back();
	}
   	cout << ans;
   return 0;
 }

16全排列2

//leetcode
class Solution {
public:
    vector<int> v;
    vector<vector<int>>ans;
    int vis[10];
    vector<vector<int>> permuteUnique(vector<int>& nums) {
        sort(nums.begin(),nums.end());
        
        dfs(nums);
        return ans;
    }
    void dfs(vector<int>& nums){
        int n = nums.size();
        if(v.size() == n){
            ans.push_back(v);
            return;
        }
        for(int i = 0; i < n; i++){
            if(vis[i])continue;
            if(i > 0 && nums[i] == nums[i - 1] && vis[i - 1] == 0) continue;//树层去重
                vis[i] = 1;
                v.push_back(nums[i]);
                dfs(nums);
                v.pop_back();
                vis[i] = 0;
            
        }
    }
};

解题思路

经典的回溯问题,但分解开来看就很简单了

1 初始化:

vector<vector<string>> ans;//答案
vector<string> v(n,string(n,'.'));//二维矩阵存图,vector是一个数组,每个数组元素又是string类型,所以可以看成C语言里char类型的二维数组
  1. 按行进行DFS递归
void dfs(int u, int n,vector<string>& v){//u代表下标为u的行
        if(u == n){
            ans.push_back(v);
            return;
        }
        for(int i = 0; i < n; i++){
            if(check(u,i,n,v)){
                v[u][i] = 'Q';
                dfs(u + 1, n,v);
                v[u][i] = '.';
            }
        }
    }

3 根据题目条件判断:不能同行 同列 同斜线,同行问题不会出现,因为咱们是按照行来递归遍历的,所以只需要判断同列 同斜线问题

int check(int x, int y,int n,vector<string> &v){
        for(int i = 0; i < x; i++){
            if(v[i][y] == 'Q') return 0;
        }
        for(int i = x - 1, j = y - 1; i >= 0&&j >= 0; i--, j--){
            if(v[i][j] == 'Q') return 0;
        }
        for(int i = x - 1, j = y + 1; i >= 0 && j <= n; i--,j++){
            if(v[i][j] == 'Q') return 0;
        }
        return 1;
    }
n皇后
class Solution {
public:
    
    vector<vector<string>> ans;
    vector<vector<string>> solveNQueens(int n) {
            vector<string> v(n,string(n,'.'));
            dfs(0,n,v);
            return ans;
    }
    int check(int x, int y,int n,vector<string> &v){
        for(int i = 0; i < x; i++){
            if(v[i][y] == 'Q') return 0;
        }
        for(int i = x - 1, j = y - 1; i >= 0&&j >= 0; i--, j--){
            if(v[i][j] == 'Q') return 0;
        }
        for(int i = x - 1, j = y + 1; i >= 0 && j <= n; i--,j++){
            if(v[i][j] == 'Q') return 0;
        }
        return 1;
    }
    void dfs(int u, int n,vector<string>& v){
        if(u == n){
            ans.push_back(v);
            return;
        }
        for(int i = 0; i < n; i++){
            if(check(u,i,n,v)){
                v[u][i] = 'Q';
                dfs(u + 1, n,v);
                v[u][i] = '.';
            }
        }
    }
};

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Solidworks界面左边FeatureManager/设计树/模型树/树区域/零件树/零件栏不见了

Solidworks界面左边FeatureManager/设计树/模型树/树区域/零件树/零件栏不见了&#xff0c;按F9还原/隐藏&#xff0c;有的笔记本按FnF9

Gin 获取请求参数

POST 请求参数 Gin 获取Post请求URL参数有三种方式 func (c *Context) PostForm(key string) string func (c *Context) DefaultPostForm(key, defaultValue string) string func (c *Context) GetPostForm(key string) (string, bool)大多数情况下使用的是application/x-www…

ffmpeg maxrate 导致转码输出的内容包含随机性

https://trac.ffmpeg.org/wiki/Limiting%20the%20output%20bitrate 问题 领导提出了一个问题&#xff0c;为什么转码后的视频大小字节数据都不一样&#xff0c;这问到我了&#xff0c;一时语塞。查一下吧&#xff0c;没有什么资料支撑。主动试一下。 尝试 首先尝试一下直接…

安卓 OpenGL ES 学习笔记

文章目录 OpenGL 学习笔记OpenGL 是什么&#xff1f;OpenGL ES是什么&#xff1f;怎么用&#xff1f;hello world如何实现动画效果 参考文章 OpenGL 学习笔记 OpenGL 是什么&#xff1f; OpenGL&#xff08;Open Graphics Library&#xff09;是一个跨平台的图形编程接口&…

EMMC的介绍

1、emmc的含义 eMMC (Embedded Multi Media Card)是MMC协会订立、主要针对手机或平板电脑等产品的内嵌式存储器标准规格。eMMC在封装中集成了一个控制器&#xff0c;提供标准接口并管理闪存&#xff0c;使得手机厂商就能专注于产品开发的其它部分&#xff0c;并缩短向市场推出产…

ChatGPT提示技巧——零,一和少量示例提示

ChatGPT提示技巧——零&#xff0c;一和少量示例提示 ​ 零样本(zero-shot)、少样本(few-shot)和单样本(one-shot)提示是用于在最少或没有示例的情况下从ChatGPT生成文本的技巧。这些技巧用于当某个具体任务有限定数据的时候或者任务是新的并且没有很好的定义的时候。 提示格…

吴恩达deeplearning.ai:数据增强数据合成迁移学习

以下内容有任何不理解可以翻看我之前的博客哦&#xff1a;吴恩达deeplearning.ai专栏 让我们看看为你的程序添加数据的技巧。在构建神经网络的时候&#xff0c;我们总是想要更多的数据&#xff0c;但是获取更多的数据往往是十分昂贵又缓慢的。相反地&#xff0c;添加数据的另一…

例行性工作(at,crontab)

目录 单一执行的例行性工作at 语法 选项 时间格式 at的工作文件存放目录 at工作的日志文件 实例 命令总结&#xff1a; 循环执行的例行性工作crond 语法 选项 crontab工作调度对应的系统服务 crontab工作的日志文件 用户定义计划任务的文件所在目录 动态查看 crontab文件格式 文…

ThreadLocal, InheritableThreadLocal和TransmittableThreadLocal

ThreadLocal, InheritableThreadLocal和TransmittableThreadLocal ThreadLocal(TL) 后续部分地方会使用ThraedLocal简称为TL 什么是TL? ThreadLocal是Java中的一个类, 也称为线程本地变量, 它提供了线程局部变量的功能。每个ThreadLocal对象都可以存储一个线程本地的变量副…

Service Mesh:如何为您的微服务架构带来可靠性和灵活性

在云原生架构中&#xff0c;Service Mesh 技术成为了微服务架构中不可或缺的一环。本文灸哥将和你一起探讨 Service Mesh 技术的原理、功能和实践&#xff0c;帮助架构师和开发人员更好地理解和应用这一关键技术。 1、Service Mesh 技术概述 Service Mesh 又称为服务网格&…

Vue3+ts(day01:Vue3简介、初始化Vue3工程)

学习源码可以看我的个人前端学习笔记 (github.com):qdxzw/frontlearningNotes 觉得有帮助的同学&#xff0c;可以点心心支持一下哈&#xff08;笔记是根据b站上学习的尚硅谷的前端视频【张天禹老师】&#xff0c;记录一下学习笔记&#xff0c;用于自己复盘&#xff0c;有需要学…

事务失效的八种情况!!!!

一、非publi修饰的方法。 /*** 私有方法上的注解&#xff0c;不生效&#xff08;因私有方法Spring扫描不到该方法&#xff0c;所以无法生成代理&#xff09;*/ Transactional private boolean test() {//test code }二、类内部访问。 类内部非直接访问带注解标记的方法 B&…

乐高wedo硬件编程

文章目录&#xff1a; 一&#xff1a;wedo零件认识 1.砖块 2.薄片 3.滑片 4.梁 5.轴 6.销 7.齿轮 8.连接器 9.装饰零件 10.电子零件 11.轮胎 12.柔性零件 二&#xff1a;软件下载安装 1.下载安装 2.使用 三&#xff1a;软件里面的指令模块介绍 绿色部分 …

Leetcode3071. 在矩阵上写出字母 Y 所需的最少操作次数

Every day a Leetcode 题目来源&#xff1a;3071. 在矩阵上写出字母 Y 所需的最少操作次数 解法1&#xff1a;模拟 统计 Y 中的元素出现次数&#xff0c;记到一个长为 3 的数组 cnt1 中。统计不在 Y 中的元素出现次数&#xff0c;记到一个长为 3 的数组 cnt2 中。 计算最多…

Linux-socket套接字

前言 在当今数字化时代&#xff0c;网络通信作为连接世界的桥梁&#xff0c;成为计算机科学领域中至关重要的一部分。理解网络编程是每一位程序员必备的技能之一&#xff0c;而掌握套接字编程则是深入了解网络通信的关键。本博客将深入讨论套接字编程中的基本概念、常见API以及…

(五)关系数据库标准语言SQL

注&#xff1a;课堂讲义使用的数据库 5.1利用SQL语言建立数据库 5.1.1 create Database 5.1.2 create schema...authorization... 创建数据库和创建模式的区别&#xff1a; 数据库是架构的集合&#xff0c;架构是表的集合。但在MySQL中&#xff0c;他们使用的方式是相同的。 …

电脑工作电压是多少你要看看光驱电源上面标的输入电压范围

要确定电脑的工作电压&#xff0c;必须查看电源上标注的输入电压范围。 国内法规规定民用220V电压范围为10%-15%&#xff0c;也就是说通信220V电压正常范围为187--242V&#xff0c;供电设备一般为180V。 --250V电压范围&#xff0c;即正常情况下电脑电源电压不低于187V即可工作…

4.1k star,官方出品的redis桌面管理工具——redislnsight

导航 令人抓狂的大key加载RedisInsight 简介RedisInsight的亮点GitHub 地址安装和使用RedisInsight 下载安装 使用RedisInsight redis数据库可视化直观的CLI&#xff08;Command-Line Interface&#xff09;日志分析和命令分析 结语参考 令人抓狂的大key加载 工欲善其事必先利…

查询IP地址保障电商平台安全

随着电子商务的快速发展&#xff0c;网购已经成为人们日常生活中不可或缺的一部分。然而&#xff0c;网络交易安全一直是人们关注的焦点之一&#xff0c;尤其是在面对日益频发的网络诈骗和欺诈行为时。为了提高网购平台交易的安全性&#xff0c;一种有效的方法是通过查询IP地址…

每周一算法:A*(A Star)算法

八数码难题 题目描述 在 3 3 3\times 3 33 的棋盘上&#xff0c;摆有八个棋子&#xff0c;每个棋子上标有 1 1 1 至 8 8 8 的某一数字。棋盘中留有一个空格&#xff0c;空格用 0 0 0 来表示。空格周围的棋子可以移到空格中。要求解的问题是&#xff1a;给出一种初始布局…