• 数独的暴力破解法


    这几天微博上面有条信息,说某数学家花了几个月发现了个数独的问题,只有一种解法,反正就是很难解。我把我几年前写的解数独的程序来跑了下,一瞬间就出来。现在把代码贴出来,顺便说下思路。

    这个其实随便一个搞了ACM的很快就可以写出来。

    #include "stdio.h"
    
    int R[9];
    int C[9];
    int G[9];
    int M[9][9];
    
    bool dfs(int x,int y)
    {
        if(x == 9)
        {
            for (int i = 0; i < 9; i++)
            {
                for(int j = 0; j < 9; j++)
                {
                    printf("%d ", M[i][j] + 1);
                }
                printf("\n");
            }
            printf("OK");
            return true;
        }
    
        if(M[x][y] != -1)
        {
            return dfs(x+(y+1)/9,(y+1)%9);
        }
    
        int z = x/3*3 + y/3;
        int e = C[x]|R[y]|G[z];
        if(e == 511)
            return false;
    
        for(int i = 0; i < 9; i++)
        {
            if ((e|(1<<i)) != e)
            {
                C[x] |= 1<<i;
                R[y] |= 1<<i;
                G[z] |= 1<<i;
                int old    = M[x][y];
                M[x][y]  = i;
    
                if(dfs(x+(y+1)/9,(y+1)%9))
                    return true;
                
                M[x][y]  = old;
                C[x] ^= 1<<i;
                R[y] ^= 1<<i;
                G[z] ^= 1<<i;
            }
        }
        return false;
    }
    
    int main()
    {
        int  num;
        char row[10];
        for (int i = 0; i < 9; i++)
        {
            for(int j = 0; j < 9; j++)
            {
                M[i][j] = -1;
            }
        }
    
        for(int i = 0;i < 9;i++)
        {
            scanf("%s",row);
            for(int j = 0;j < 9;j++)
            {
                if(row[j] != '?')
                {
                    num = row[j]-'1';
                    M[i][j] = num;
                    R[j]   |= 1<<num;
                    C[i]   |= 1<<num;
                    G[i/3*3 + j/3] |= 1<<num;
                }
            }
        }
        dfs(0, 0);
        while(1);
        return 0;
    }

    我觉得值得一提的是里面的状态压缩。

    R[], C[]数组里面的一个数表示某行,某列已经出现的数字,R[0]表示第一行(列)已经出现的数,用一个bit表示某位是否出现,因此只用到了最低的9bit。

    G[]表示每个3*3格子出现了的数。

    M[][]表示当前已经填了的局面,如果为-1表示该位未知,则从小到大试添格子所在的行,列,3*3格子都没有出现的数字。状态压缩后则行,列,3*3已出现的数字简单用或就可以算出来。

  • 相关阅读:
    hexo常用命令笔记
    给hexo添加评论系统
    npm 使用代理
    几种网页重定向(自动跳转)的方法
    使用hexo搭建github博客
    在Pythonanywhere上部署Django
    Apache .htaccess语法之RewriteRule
    为Github项目创建文档
    Windows下WordPress搭建博客过程
    Windows下Discuz搭建论坛过程
  • 原文地址:https://www.cnblogs.com/cmzbjl/p/3102789.html
Copyright © 2020-2023  润新知