Acwing-166-数独(搜索)

有些话、适合烂在心里 提交于 2019-11-29 21:05:28

链接:

https://www.acwing.com/problem/content/168/

题意:

数独是一种传统益智游戏,你需要把一个9 × 9的数独补充完整,使得图中每行、每列、每个3 × 3的九宫格内数字1~9均恰好出现一次。

请编写一个程序填写数独。

思路:

二进制记录每一行, 每一列, 每一块的数值使用情况, 每次从最小的开始枚举.

代码:

#include <bits/stdc++.h>
using namespace std;

char input[90];
char Map[10][10];
int Cnt[1000], Num[1000];
int row[10], col[10], gri[10];
int cnt;

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

int GetP(int x, int y)
{
    return (x/3)*3+(y/3);
}

void Change(int x, int y, int p)
{
    row[x] ^= (1<<p);
    col[y] ^= (1<<p);
    gri[GetP(x, y)] ^= (1<<p);
}

bool Dfs(int las)
{
//    cout << las << endl;
    if (las == 0)
        return true;
    int tmp = 10, x, y;
    for (int i = 0;i < 9;i++)
    {
        for (int j = 0;j < 9;j++)
        {
            if (Map[i][j] != '.')
                continue;
            int val = row[i]&col[j]&gri[GetP(i, j)];
            if (val == 0)
                return false;
            if (Cnt[val] < tmp)
            {
                tmp = Cnt[val];
                x = i, y = j;
            }
        }
    }
    int val = row[x]&col[y]&gri[GetP(x, y)];
    while (val > 0)
    {
        int z = Num[Lowbit(val)];
        Map[x][y] = z+'1';
        Change(x, y, z);
        if (Dfs(las-1))
            return true;
        Change(x, y, z);
        Map[x][y] = '.';
        val -= Lowbit(val);
    }
    return false;
}

int main()
{
    for (int i = 0;i < (1<<9);i++)
    {
        for (int j = i;j > 0;j -= Lowbit(j))
            Cnt[i]++;
    }
    for (int i = 0;i < 9;i++)
        Num[1<<i] = i;
    while (scanf("%s", input) && input[0] != 'e')
    {
        for (int i = 0;i < 9;i++)
        {
            for (int j = 0;j < 9;j++)
                Map[i][j] = input[i*9+j];
        }
        for (int i = 0;i < 9;i++)
            row[i] = col[i] = gri[i] = (1<<9)-1;
        cnt = 0;
        for (int i = 0;i < 9;i++)
        {
            for (int j = 0;j < 9;j++)
            {
                if (Map[i][j] != '.')
                    Change(i, j, Map[i][j]-'1');
                else
                    cnt++;
            }
        }
        Dfs(cnt);
        for (int i = 0;i < 9;i++)
        {
            for (int j = 0;j < 9;j++)
                input[i*9+j] = Map[i][j];
        }
        puts(input);
    }

    return 0;
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!