IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 人工智能 -> 166. 数独 DFS 之 剪枝 二进制 位运算 优化 思维 -> 正文阅读

[人工智能]166. 数独 DFS 之 剪枝 二进制 位运算 优化 思维

题目

在这里插入图片描述

题解思路

4大剪枝常用剪枝策略
在这里插入图片描述
首先进行优化搜索顺序,每次搜索可以放的数最少的的点 。

再根据行列九宫格不能相同,想到位运算优化(我是想不到)。

利用按位与 & 的 清零性质 (即一位为0 按位与出来的一定是 0 )
用 0 表示放了这个位置的数 , 1表示没放 。

这样的话 每行列和九宫格的 所有状态 就可以用一个 2 ^ 9 - 1 的 数 表示了

其次这里可以lowbit来快速找出1的位置来让我们放数 。

在这里插入图片描述

实现

初始化

将 所有行列 子棋盘的状态变为1 即表示都没放 即 2 ^ 9 - 1

我们先将 棋盘中已经有的数放入棋盘 , 将 这个数的行列以及归属的子棋盘 的状态更新 。 即 减上这个数的二进制 表示 。 ( 如 2 (10) 4(1000)) 代表这个位置放了数 ( 0 代表放了)。

这里可以写个函数 因为之后我们会再放数进去 。

再进去 dfs 去搜索出能放的答案

每次搜索可以放的数最少的的点

这样我们要对整个棋盘搜索出每个可以放的位置 可以放的数量 (即状态为1 的总数 ) 取 min
这里我们只有 对这个位置的3个状态 & 可以得出他的总状态 ,但是lowbit只能得出最低位的1 , 这样的话 我们要预处理出一个代表每个状态有多少个1的数组 nosum

然后取出这个1最小的状态 , 利用lowbit 拿出 每个 1 进行尝试放入数 。
这样又有问题了,我们只有这个状态值的1,但是我们要的是直接得出这个位置放什么数,
又是预处理。。。,我们利用一个数组mp存入每个1的真正代表的数 即 100 代表3 1000 代表 4
但是位运算左移缺了1 1 >> 1 得出的是 10 1>>2 得出 100 这样我们就在放入棋盘的函数中修改让他把数自增一个1即直接加 '1 ’

这样我们只需在尝试放入后,进行复原(回溯) 。
但是我们要保证答案在原地要怎么呢 ?

复原前需要知道这个点是不是答案。这样我们只需要在搜索到答案的时候return true , 当dfs返回true时就不需要复原了。

这题磕了很久,没有找到写的仔细的博客,自己写了个。

AC代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <algorithm>
#include <map>
#include <string>
using namespace std;

const int N = 9 , M = 1 << N ;

int nosum [M] , mp[M] ;
int row[N] , col [N] , cell[3][3] ;
char st[100] ;


void init()
{
     for (int i = 0 ; i < N ; i++ )
        row[i] = col[i] = (1 << N ) - 1 ;

     for (int i = 0 ; i < 3 ; i++ )
        for (int j = 0 ; j < 3 ; j++ )
            cell[i][j] = (1 << N) - 1 ;
}

int lowbit (int x )
{
    return x & -x ;
}

void draw ( int x ,int y , int t , bool is_set )
{
    if ( is_set )
        st [ x * N + y ] = '1' + t ;
    else
        st [ x*N + y ] = '.' ;

    int v = 1 << t ;

    if ( ! is_set )
        v = - v ;

    row[x] -= v ;
    col[y] -= v ;
    cell[ x / 3 ][ y / 3 ] -= v ;

}

int gett( int x , int y )
{
    return cell[x/3][y/3] & row[x] & col[y] ;
}

bool  dfs( int p )
{
    if ( p == 0 )
        return true ;
    int mi = N ;
    int x , y ;
    for (int i = 0 ; i < N ; i++ )
        for (int j = 0 ; j < N ; j++ )
        {
            if ( st [ i*N + j ] == '.' )
            {
                int sat = gett( i , j ) ;
                if ( nosum[sat] < mi )
                {
                    mi = nosum[sat] ;
                    x = i ;
                    y = j ;
                }
            }
        }

    int sat = gett( x , y ) ;
    for (int i = sat ; i ; i -= lowbit(i) )
    {
        int t = mp[lowbit(i)] ;
        draw( x , y , t , 1 ) ;
        if ( dfs( p - 1 ) )
            return true ;
        draw( x , y , t , 0 ) ;
    }
    return false ;
}


int main ()
{
    ios::sync_with_stdio(false);

    for (int i = 0; i < N; i ++ )
        mp[1 << i] = i;

    for (int i = 0 ; i < 1 << N ; i++ )
        for (int j = 0 ; j < N ; j++ )
            nosum[ i ] += i >> j & 1 ;

    while ( cin >> st , st[0] != 'e' )
    {
        init() ;

        int cnt = 0 ;

        for (int i = 0 , k = 0 ; i < N ; i++ )
            for (int j = 0 ; j < N ; j++ , k++ )
            {
                if ( st[k] != '.' )
                {
                    int t = st[k] - '1' ;
                    draw( i , j , t  , 1 ) ;
                }else
                    cnt++ ;

            }

        dfs(cnt) ;

        cout << st << "\n" ;
    }

    return 0 ;
}

  人工智能 最新文章
2022吴恩达机器学习课程——第二课(神经网
第十五章 规则学习
FixMatch: Simplifying Semi-Supervised Le
数据挖掘Java——Kmeans算法的实现
大脑皮层的分割方法
【翻译】GPT-3是如何工作的
论文笔记:TEACHTEXT: CrossModal Generaliz
python从零学(六)
详解Python 3.x 导入(import)
【答读者问27】backtrader不支持最新版本的
上一篇文章      下一篇文章      查看所有文章
加:2021-10-16 19:38:58  更:2021-10-16 19:41:32 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/27 10:27:19-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码