数独(16*16)DFS剪枝优化解法

这篇博客探讨了使用DFS解决16*16数独问题的优化策略,包括按空格、行、列和16宫格进行剪枝,以及判断解题边界的技巧。还提到了两道相关题目和AC代码。
摘要由CSDN通过智能技术生成

DFS专题合集:

DFS连通性模型

DFS剪枝与优化

据说填充数独用DLX是最快的,笔者不会DLX,故使用DFS并无限优化。

在这里只说明一些优化操作。

一:优化顺序:

同9*9的数独,我们找到可以填充字母最少的格点,从这个点开始DFS,分支数目最少。

二:可行性剪枝

1:按空格剪枝:

我们找到每个为填充字母的格点,判断其是否可以填充字母,如果不可以,则直接剪枝;如果只可以填充一个字母,则将其填入。

2:按行剪枝:

枚举每行,如果这一行有字母不可以填充,则直接剪枝,如果只可以填充一个字母,则填入。

3:按列剪枝:

枚举每列,如果这一行有字母不可以填充,则直接剪枝,如果只可以填充一个字母,则填入。

4:按16宫格剪枝

枚举每个16宫格,如果这一行有字母不可以填充,则直接剪枝,如果只可以填充一个字母,则填入。

三:判断边界:

当格子内没有空格时,则为一组可行方案。

四:题目以及AC代码:

洛谷双倍经验!

两道黑题,也是第一次做黑题。

 

 题目传送门:

SP1110    UVA1309

注意细节:UVA测评不允许输出最后有多余的空格或者换行。

SP1110 AC代码:

#include<iostream>
#include<cstring>

#define AC return 0;

using namespace std;
const int N=16;
int map[1<<N],ones[1<<N];
char str[N][N+1];
int state[N][N];
char backstr[N*N+1][N][N+1];
int backstate[N*N+1][N][N],backstate2[N*N+1][N][N];

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

void draw(int x,int y,int c)
{
    str[x][y]='A'+c;
    
    for(int i=0;i<N;i++)
    {
        state[i][y] &= ~(1<<c);
        state[x][i] &= ~(1<<c);
    }
    
    int sx=x/4*4,sy=y/4*4;
    for(int i=0;i<4;i++)
        for(int j=0;j<4;j++)
            state[sx+i][sy+j] &= ~(1<<c);
            
    state[x][y]=1<<c;
}

bool dfs(int cnt)
{
    
    if(!cnt) return 1;
    int kcnt=cnt;
    memcpy(backstr[kcnt],str,sizeof(str));
    memcpy(backstate[kcnt],state,sizeof(state));
    
    //枚举每个空格是否有格子不能填,不能填直接剪枝,只能填一个就填上。
    for(int i=0;i<N;i++)
    {
        for(int j=0;j<N;j++)
        {
            if(str[i][j]=='-')
            {
                if(!state[i][j])
                {
                    memcpy(str,backstr[kcnt],sizeof(str));
                    memcpy(state,backstate[kcnt],sizeof(state));
                    return 0;
                }
                
                if(ones[state[i][j]]==1)
                {
                    draw(i,j,map[state[i][j]]);
         
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值