数组 - 八皇后 - 困难

*************

C++

topic: 面试题 08.12. 八皇后 - 力扣(LeetCode)

*************

Good morning, gays, Fridary angin and try the hard to celebrate.

Inspect the topic:

This topic I can understand it in a second.  And I do rethink a movie, which talks anout chess

This title imposes the same rectructions on queens as the rules for queens in chess. In chess, queens may move either stright and diagonally. And may by this code was applied in some chees games.

 

Back to the topic, try to find the topics I've done which is similar to t his topic. It seems like no one like this. 

Use matrix, I learned matrix from a teacher, Master Tang:

Greedy algorithm, I did yesterday, may work. Every step goes to the best way, and might have the happy ending in the end.

First, put the queen in matrix[1][1], then put the second  row, maxtrix[2][1] is forbidden cuz it is in the first column. Matrix[2][2] is forbidden cuz it in the diagonal. Put it in matrix[2][3]. Actally, make sure that  matrix[i][i] put nothing. 

From the first row,  put the queen in the first column.

To the second row, put the queen in the first column, check if it conflicts with previous queens. If not, add a row. If so, change a column.

Take an example, N = 13, The position-array has 13 elements, each ranges from 0 to 12. 

For each increatment, generate a new array of positions. Check if the condition is satisfied for each array of positions. If satisfied, save it.                                                                         

When the last queen find her place, the war end.

This is a really new algorithm called Backtracking Algorithm.A backtracking algorithm is an algorithm that tries different things until it finds the right answer. It avoids doing unnecessary work. Backtracking algorithms are used to solve many kinds of problems. The usage of backtracking algorithm follows:

void backtrack(路径参数, 选择列表参数) {
    // 检查是否满足结束条件
    if (满足结束条件) {
        // 处理解决方案
        return;
    }

    // 遍历选择列表
    for (auto i : 选择列表) {
        // 添加当前选项到路径
        路径.push_back(i);

        // 进行递归
        backtrack(路径, 更新的选择列表);

        // 回溯,移除当前选项
        路径.pop_back();
    }
}

Try to write the code:

need to find a right way to describe the chess board. matrix N × N doesnot work, the reason of it is that memory is everything for the computer, N × N use tooooooooooooo much storage. Never think about it. 

Every queen has different row, so it can be used in one-line matrix, for instace:

 it can be described as 4 multiply 4 

  1. 1 0 0 0
  2. 0 0 1 0
  3. 0 1 0 0 
  4. 0 0 0 1

also, a smarter way to describe is as follow:

array X = [1, 3, 2, 4], which means

  1. the 1st  queen laies at row 1 column 1,
  2. the 2nd queen laies at row 2 column 3,
  3. the 3rd queen laies at row 3 column  2,
  4. the 4th queen laies at row 4 column  4,

but how to tell the computer that the queens cannot stay in the diagonal? 

the same color's position is illegal. It can EZ tell that two queens on the same diagonal if and only if their row and column differences are equal. 
|row1 - row4| == |column4 - column1|

There's no need to double-check each row and column; only the diagonals. To check more efficiently, record which columns and diagonals have been used when placing the queens.

record this in three sets:

  1. Columns where queens have already been placed.
  2. Primary diagonal: row-column values on the same primary diagonal.
  3. Sub-diagonal: row + column values where identical values are on the same sub-diagonal.

 so make up the code to describe the 3 sets in backtrack structure:

void backtrack_bit(int n, int row, unsigned long long cols_mask,
                       unsigned long long diag1_mask, unsigned long long diag2_mask,
                       vector<int>& queens, vector<vector<string>>& result) 
{
    // 检查是否满足结束条件
    if (满足结束条件) {
        // 处理解决方案
        return;
    }

    // 遍历选择列表
    for (auto i : 选择列表) {
        // 添加当前选项到路径
        路径.push_back(i);

        // 进行递归
        backtrack(路径, 更新的选择列表);

        // 回溯,移除当前选项
        路径.pop_back();
    }
}

move next, what is 满足结束条件? it is the row == n, the last queen finds her palace.

void backtrack_bit(int n, int row, unsigned long long cols_mask,
                       unsigned long long diag1_mask, unsigned long long diag2_mask,
                       vector<int>& queens, vector<vector<string>>& result) 
{
    // 检查是否满足结束条件
    if (row == n) {
        // 处理解决方案
        return;
    }

    // 遍历选择列表
    for (auto i : 选择列表) {
        // 添加当前选项到路径
        路径.push_back(i);

        // 进行递归
        backtrack(路径, 更新的选择列表);

        // 回溯,移除当前选项
        路径.pop_back();
    }
}

and what is 处理解决方案? That is return the result. But pay vital attention to the result like this:

make sure that the code return a string:

 

void backtrack_bit(int n, int row, unsigned long long cols_mask,
                       unsigned long long diag1_mask, unsigned long long diag2_mask,
                       vector<int>& queens, vector<vector<string>>& result) 
{
    // 检查是否满足结束条件
    if (row == n) {
        // 生成棋盘的字符串表示
            vector<string> board;
            for (int i = 0; i < n; i++) {
                string row_str(n, '.'); // 初始化一行,全部为'.'
                row_str[queens[i]] = 'Q'; // 在皇后的位置放置'Q'
                board.push_back(row_str); // 将这一行添加到棋盘表示中
            }
            result.push_back(board); // 将整个棋盘添加到结果中

            return;
    }

    // 遍历选择列表
    for (auto i : 选择列表) {
        // 添加当前选项到路径
        路径.push_back(i);

        // 进行递归
        backtrack(路径, 更新的选择列表);

        // 回溯,移除当前选项
        路径.pop_back();
    }
}

the next step is 遍历选择列表. This is the most diffcult step, including how to lay the queens. Make sure that every column has been visited.

void backtrack_bit(int n, int row, unsigned long long cols_mask,
                       unsigned long long diag1_mask, unsigned long long diag2_mask,
                       vector<int>& queens, vector<vector<string>>& result) 
{
    // 检查是否满足结束条件
    if (row == n) {
        // 生成棋盘的字符串表示
            vector<string> board;
            for (int i = 0; i < n; i++) {
                string row_str(n, '.'); // 初始化一行,全部为'.'
                row_str[queens[i]] = 'Q'; // 在皇后的位置放置'Q'
                board.push_back(row_str); // 将这一行添加到棋盘表示中
            }
            result.push_back(board); // 将整个棋盘添加到结果中

            return;
    }

    // 遍历选择列表
    for (int col = 0; col < n; col++) {
        // 添加当前选项到路径
        路径.push_back(i);

        // 进行递归
        backtrack(路径, 更新的选择列表);

        // 回溯,移除当前选项
        路径.pop_back();
    }
}

If there's already a queen in the column, main diagonal, or sub-diagonal where you're placing the queen, skip that spot.

void backtrack_bit(int n, int row, unsigned long long cols_mask,
                       unsigned long long diag1_mask, unsigned long long diag2_mask,
                       vector<int>& queens, vector<vector<string>>& result) 
{
    // 检查是否满足结束条件
    if (row == n) {
        // 生成棋盘的字符串表示
            vector<string> board;
            for (int i = 0; i < n; i++) {
                string row_str(n, '.'); // 初始化一行,全部为'.'
                row_str[queens[i]] = 'Q'; // 在皇后的位置放置'Q'
                board.push_back(row_str); // 将这一行添加到棋盘表示中
            }
            result.push_back(board); // 将整个棋盘添加到结果中

            return;
    }

   
 // 遍历选择列表
    for (int col = 0; col < n; col++) {

        if ((cols_mask & (1ULL << col)) ||
                (diag1_mask & (1ULL << d1)) ||
                (diag2_mask & (1ULL << d2))) {
                continue; // 如果不安全,跳过这一列
            }




        // 添加当前选项到路径

        路径.push_back(i);



        // 进行递归
        backtrack(路径, 更新的选择列表);



        // 回溯,移除当前选项
        路径.pop_back();
    }
}

in this special code :

if ((cols_mask & (1ULL << col)) ||
                (diag1_mask & (1ULL << d1)) ||
                (diag2_mask & (1ULL << d2))) {
                continue; // 如果不安全,跳过这一列
            }

1ULL meas 1 unsigned long long,  << means move 1 step to the left.

diag_mask is an integer, for example:

if col == 2, in binary system is 10;  1ULL << 2 is 4, in binary system is 100

see, in binary system, int 1 moves one step left.

then put the queen

void backtrack_bit(int n, int row, unsigned long long cols_mask,
                       unsigned long long diag1_mask, unsigned long long diag2_mask,
                       vector<int>& queens, vector<vector<string>>& result) 
{
    // 检查是否满足结束条件
    if (row == n) {
        // 生成棋盘的字符串表示
            vector<string> board;
            for (int i = 0; i < n; i++) {
                string row_str(n, '.'); // 初始化一行,全部为'.'
                row_str[queens[i]] = 'Q'; // 在皇后的位置放置'Q'
                board.push_back(row_str); // 将这一行添加到棋盘表示中
            }
            result.push_back(board); // 将整个棋盘添加到结果中

            return;
    }

   
 // 遍历选择列表
    for (int col = 0; col < n; col++) {

        if ((cols_mask & (1ULL << col)) ||
                (diag1_mask & (1ULL << d1)) ||
                (diag2_mask & (1ULL << d2))) {
                continue; // 如果不安全,跳过这一列
            }

 // 在当前位置放置皇后
            queens.push_back(col);





        // 进行递归
        backtrack(路径, 更新的选择列表);



        // 回溯,移除当前选项
        路径.pop_back();
    }
}

and move to the next row:

void backtrack_bit(int n, int row, unsigned long long cols_mask,
                       unsigned long long diag1_mask, unsigned long long diag2_mask,
                       vector<int>& queens, vector<vector<string>>& result) 
{
    // 检查是否满足结束条件
    if (row == n) {
        // 生成棋盘的字符串表示
            vector<string> board;
            for (int i = 0; i < n; i++) {
                string row_str(n, '.'); // 初始化一行,全部为'.'
                row_str[queens[i]] = 'Q'; // 在皇后的位置放置'Q'
                board.push_back(row_str); // 将这一行添加到棋盘表示中
            }
            result.push_back(board); // 将整个棋盘添加到结果中

            return;
    }

   
 // 遍历选择列表
    for (int col = 0; col < n; col++) {

        if ((cols_mask & (1ULL << col)) ||
                (diag1_mask & (1ULL << d1)) ||
                (diag2_mask & (1ULL << d2))) {
                continue; // 如果不安全,跳过这一列
            }

 // 在当前位置放置皇后
            queens.push_back(col);





        // 递归到下一行
            backtrack_bit(n, row + 1, cols_mask | (1ULL << col),
                          diag1_mask | (1ULL << d1), diag2_mask | (1ULL << d2),
                          queens, result);


        // 回溯,移除当前选项
        路径.pop_back();
    }
}

and next

void backtrack_bit(int n, int row, unsigned long long cols_mask,
                       unsigned long long diag1_mask, unsigned long long diag2_mask,
                       vector<int>& queens, vector<vector<string>>& result) 
{
    // 检查是否满足结束条件
    if (row == n) {
        // 生成棋盘的字符串表示
            vector<string> board;
            for (int i = 0; i < n; i++) {
                string row_str(n, '.'); // 初始化一行,全部为'.'
                row_str[queens[i]] = 'Q'; // 在皇后的位置放置'Q'
                board.push_back(row_str); // 将这一行添加到棋盘表示中
            }
            result.push_back(board); // 将整个棋盘添加到结果中

            return;
    }

   
 // 遍历选择列表
    for (int col = 0; col < n; col++) {

        if ((cols_mask & (1ULL << col)) ||
                (diag1_mask & (1ULL << d1)) ||
                (diag2_mask & (1ULL << d2))) {
                continue; // 如果不安全,跳过这一列
            }

 // 在当前位置放置皇后
            queens.push_back(col);





        // 递归到下一行
            backtrack_bit(n, row + 1, cols_mask | (1ULL << col),
                          diag1_mask | (1ULL << d1), diag2_mask | (1ULL << d2),
                          queens, result);


        // 回溯,移除当前皇后
            queens.pop_back();
    }
}

dont forget to initialize at the very beginning:

class Solution {
public:
    // 主函数,接收一个整数n,表示棋盘的大小
    vector<vector<string>> solveNQueens(int n) {
        vector<vector<string>> result; // 用于存储所有可能的解
        vector<int> queens; // 用于存储当前放置皇后的列位置
        // 从第0行开始回溯
        backtrack_bit(n, 0, 0, 0, 0, queens, result);
        return result; // 返回所有可能的解
    }

private:
    // 回溯函数,参数包括棋盘大小n,当前行row,以及三个掩码
    void backtrack_bit(int n, int row, unsigned long long cols_mask,
                       unsigned long long diag1_mask, unsigned long long diag2_mask,
                       vector<int>& queens, vector<vector<string>>& result) {
        // 如果到达最后一行,说明找到了一个解
        if (row == n) {
            // 生成棋盘的字符串表示
            vector<string> board;
            for (int i = 0; i < n; i++) {
                string row_str(n, '.'); // 初始化一行,全部为'.'
                row_str[queens[i]] = 'Q'; // 在皇后的位置放置'Q'
                board.push_back(row_str); // 将这一行添加到棋盘表示中
            }
            result.push_back(board); // 将整个棋盘添加到结果中
            return;
        }
        // 尝试在当前行的每一列放置皇后
        for (int col = 0; col < n; col++) {
            int d1 = row - col + (n - 1); // 对角线1的索引
            int d2 = row + col; // 对角线2的索引
            // 检查当前位置是否安全
            if ((cols_mask & (1ULL << col)) ||
                (diag1_mask & (1ULL << d1)) ||
                (diag2_mask & (1ULL << d2))) {
                continue; // 如果不安全,跳过这一列
            }
            // 在当前位置放置皇后
            queens.push_back(col);
            // 递归到下一行
            backtrack_bit(n, row + 1, cols_mask | (1ULL << col),
                          diag1_mask | (1ULL << d1), diag2_mask | (1ULL << d2),
                          queens, result);
            // 回溯,移除当前皇后
            queens.pop_back();
        }
    }
};

and of course it works:

unsigned longlong can be replaced as unsigned long, to save the storge.

class Solution {
public:
    // 主函数,接收一个整数n,表示棋盘的大小
    vector<vector<string>> solveNQueens(int n) {
        vector<vector<string>> result; // 用于存储所有可能的解
        vector<int> queens; // 用于存储当前放置皇后的列位置
        // 从第0行开始回溯
        backtrack_bit(n, 0, 0, 0, 0, queens, result);
        return result; // 返回所有可能的解
    }

private:
    // 回溯函数,参数包括棋盘大小n,当前行row,以及三个掩码
    void backtrack_bit(int n, int row, unsigned long cols_mask,
                       unsigned long diag1_mask, unsigned long diag2_mask,
                       vector<int>& queens, vector<vector<string>>& result) {
        // 如果到达最后一行,说明找到了一个解
        if (row == n) {
            // 生成棋盘的字符串表示
            vector<string> board;
            for (int i = 0; i < n; i++) {
                string row_str(n, '.'); // 初始化一行,全部为'.'
                row_str[queens[i]] = 'Q'; // 在皇后的位置放置'Q'
                board.push_back(row_str); // 将这一行添加到棋盘表示中
            }
            result.push_back(board); // 将整个棋盘添加到结果中
            return;
        }
        // 尝试在当前行的每一列放置皇后
        for (int col = 0; col < n; col++) {
            int d1 = row - col + (n - 1); // 对角线1的索引
            int d2 = row + col; // 对角线2的索引
            // 检查当前位置是否安全
            if ((cols_mask & (1UL << col)) ||
                (diag1_mask & (1UL << d1)) ||
                (diag2_mask & (1UL << d2))) {
                continue; // 如果不安全,跳过这一列
            }
            // 在当前位置放置皇后
            queens.push_back(col);
            // 递归到下一行
            backtrack_bit(n, row + 1, cols_mask | (1UL << col),
                          diag1_mask | (1UL << d1), diag2_mask | (1UL << d2),
                          queens, result);
            // 回溯,移除当前皇后
            queens.pop_back();
        }
    }
};

 and here is the magic:

 consume memory ranges from 11.96 to 12.15. 

reverse upgrading, sad.

anyway 

wish me have a good weekend.

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

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

相关文章

IDEA的service窗口中启动类是灰色且容易消失

大家在学习Spring Cloud的过程中,随着项目的深入,会分出很多个微服务,当我们的服务数量大于等于三个的时候,IDEA会给我们的服务整理起来,类似于这样 但是当我们的微服务数量达到5个以上的时候,再启动服务的时候,服务的启动类就会变成灰色,而且还容易丢失 解决方法 我们按住…

threejs相机辅助对象cameraHelper

为指定相机创建一个辅助对象&#xff0c;显示这个相机的视锥。 想要在场景里面显示相机的视锥&#xff0c;需要创建两个相机。 举个例子&#xff0c;场景中有个相机A&#xff0c;想要显示相机A的视锥&#xff0c;那么需要一个相机B&#xff0c;把B放在A的后面&#xff0c;两个…

应用层协议/传输层协议(UDP)

目录 应用层 如何自定义应用层协议&#xff1f; 序列化方式 1.基于行文本的方式来传输 2.基于xml的方式 3.基于json的方式 4.yml的形式 5.protobuffer(pb)形式 传输层 端口号 协议 UDP 校验和 CRC TCP TCP/IP五层协议 应用层 -- 传输层 -- 网络层 -- 数据链路层…

cocotb value cocotb—基础语法对照篇

cocotb—基础语法对照篇 import cocotb from cocotb.triggers import Timer from adder_model import adder_model from cocotb.clock import Clock from cocotb.triggers import RisingEdge import randomcocotb.test() async def adder_basic_test(dut):"""Te…

【NoSQL数据库】Hbase基本操作——数据库表的增删改查

目录 一、Hbase原理 二、HBase数据库操作 三、遇到的问题和解决方法 一、Hbase原理 HBase的数据模型&#xff1a; 行键 时间戳 列族&#xff1a;contents 列族&#xff1a;anchor 列族&#xff1a;mime “com.cnn.www” T9 Achor:cnnsi.com”CNN” T8 Achor:…

【NLP高频面题 - LLM架构篇】大模型使用SwiGLU相对于ReLU有什么好处?

【NLP高频面题 - LLM架构篇】大模型使用SwiGLU相对于ReLU有什么好处&#xff1f; 重要性&#xff1a;★★★ &#x1f4af; NLP Github 项目&#xff1a; NLP 项目实践&#xff1a;fasterai/nlp-project-practice 介绍&#xff1a;该仓库围绕着 NLP 任务模型的设计、训练、优化…

ElementUI 问题清单

1、form 下面只有一个 input 时回车键刷新页面 原因是触发了表单默认的提交行为&#xff0c;给el-form 加上submit.native.prevent就行了。 <el-form inline submit.native.prevent><el-form-item label"订单号"><el-inputv-model"query.order…

AWS 机器学习,推动 AI 技术的健康发展

目录 一、AI 正在改变生产方式二、从炒作走向务实1、选对场景2、重视数据3、产品思维4、持续优化 三、人才是最稀缺的资源四、负责任的 AI 开发五、未来已来六、启示与思考七、结语 如果说传统软件开发是手工作坊&#xff0c;那么 AI 就像工业革命带来的机器生产。 在最新的一…

【第 1 章 初识 C 语言】1.8 使用 C 语言的 7 个步骤

目录 1.8 使用 C 语言的 7 个步骤 1.8.1 第 1 步&#xff1a;定义程序的目标 1.8.2 第 2 步&#xff1a;设计程序 1.8.3 第 3 步&#xff1a;编写代码 1.8.4 第 4 步&#xff1a;编译 1.8.5 第 5 步&#xff1a;运行程序 1.8.6 第 6 步&#xff1a;测试和调试程序 1.8.…

C++知识整理day4内存管理——new和delete详解

文章目录 1.C/C内存分布2.C语言中动态内存管理&#xff1a;malloc/realloc/calloc3.C内存管理方式3.1 new/delete操作内置类型3.2 new和delete操作自定义类型 4.malloc/free和new/delete到底什么区别&#xff1f;4.1 对于自定义类型4.2 对于自定义类型4.3 总结&#xff1a;它们…

实现跨平台 SSH 连接:从 macOS 到 Windows WSL 的完整解决方案20241203

&#x1f310; 实现跨平台 SSH 连接&#xff1a;从 macOS 到 Windows WSL 的完整解决方案 ✨ 引言 随着跨平台开发的普及&#xff0c;开发者经常需要在多系统环境中切换和协作。尤其是在 macOS 和 Windows 混合使用的开发环境中&#xff0c;通过 SSH 远程访问和管理 Windows …

检索增强生成RAG与知识图谱

检索增强生成RAG与知识图谱 一、检索增强生成&#xff08;RAG&#xff09;1、简介2、RAG 的优点3、RAG的应用场景4、RAG增强原理 二、知识图谱介绍1、简介2、知识图谱的应用场景3、优劣势分析a、优点:b、缺点: 4、应用实例5、知识图谱和图数据库的关系 一、检索增强生成&#x…

Vue前端开发-路由跳转及带参数跳转

在Vue 3中&#xff0c;由于没有实例化对象this&#xff0c;因此&#xff0c;无法通过this去访问 $route对象&#xff0c;而是通过导入一个名为 useRouter 的方法&#xff0c;执行这个方法后&#xff0c;返回一个路由对象&#xff0c;通过这个路由对象就可以获取到当前路由中的信…

第九篇:k8s 通过helm发布应用

什么是helm&#xff1f; Helm 是 Kubernetes 的包管理器。Helm 是查找、分享和使用软件构建 Kubernetes 的最优方式。 在红帽系的Linux中我们使用yum来管理RPM包&#xff0c;类似的&#xff0c;在K8s中我们可以使用helm来管理资源对象&#xff08;Deployment、Service、Ingress…

SQL——DQL分组聚合

分组聚合&#xff1a; 格式&#xff1a; select 聚合函数1(聚合的列),聚合函数2(聚合的列) from 表名 group by 标识列; ###若想方便分辨聚合后数据可在聚合函数前加上标识列&#xff08;以标识列进行分组&#xff09; 常见的聚合函数: sum(列名):求和函数 avg(列名)…

【Linux】ubuntu下一键配置vim

&#x1f525;个人主页&#x1f525;&#xff1a;孤寂大仙V &#x1f308;收录专栏&#x1f308;&#xff1a;Linux &#x1f339;往期回顾&#x1f339;&#xff1a;Linux权限&#xff08;超详细彻底搞懂Linux的权限&#xff09; &#x1f516;流水不争&#xff0c;争的是滔滔…

42_GAN网络详解(2)---常见的GAN

DCGAN CGAN 条件生成对抗网络&#xff08;Conditional Generative Adversarial Networks, CGAN&#xff09;是生成对抗网络&#xff08;Generative Adversarial Networks, GAN&#xff09;的一种变体&#xff0c;由Mehdi Mirza和Simon Osindero在2014年提出。CGAN的主要改进在…

burp常用机漏洞测试理论

声明&#xff01; 学习视频来自B站up主 **泷羽sec** 有兴趣的师傅可以关注一下&#xff0c;如涉及侵权马上删除文章&#xff0c;笔记只是方便各位师傅的学习和探讨&#xff0c;文章所提到的网站以及内容&#xff0c;只做学习交流&#xff0c;其他均与本人以及泷羽sec团队无关&a…

带权并查集和扩展域并查集的一些整理和理解(上)

请读者在有一定并查集基础上再阅读&#xff08;至少要知道什么是带权和扩展域并查集&#xff09; 在最近做题时候&#xff0c;我遇到了一些带权并查集和扩展域并查集的题目。我觉得它们都很难写也很难想&#xff0c;尤其是带权并查集我几乎第一时间无法想到是怎么做的&#xf…

一分钟快速了解SBTI科学碳目标/碳披露认证

一分钟快速了解SBTI&#xff08;Science Based Targets initiative&#xff0c;科学碳目标&#xff09;认证注意事项&#xff0c;是企业在追求可持续发展道路上不可或缺的一环。SBTI认证不仅是对企业减排承诺的权威背书&#xff0c;更是引领行业绿色转型的风向标。 在踏上SBTI认…