数独 题解

来自算法竞赛进阶指南

一道思路很好想,特别难写的题。

主要运用搜索可行性剪枝,二进制位运算优化。

没有什么难度,就是模拟。但是难写。

发一下来纪念我写了二十分钟。

#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;

const int N = 9,M = 1 << N;
int ones[M],map[M];
int row[N],col[N],cell[3][3];

char str[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;
}

void draw(int x,int y,int t,bool is_set)
{
    if(is_set) str[x * N + y] = '1' + t;
    else str[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 lowbit(int x)
{
    return x & -x;
}
int get(int x,int y)
{
  return row[x] & col[y] & cell[x / 3][y / 3];

}


bool dfs(int cnt)
{
    if(!cnt) return true;
    int minv = 10;
    int x,y;
    for(int i = 0; i < N; ++ i)
      for(int j = 0; j < N; ++ j)
      if(str[i * N + j] == '.')
        {
            int state = get(i,j);
            if(ones[state] < minv)
            {
                minv =ones[state];
                x = i,y = j;
            }
        }
    int state = get(x,y);
    for(int i = state;i ; i -= lowbit(i))
    {
        int t = map[lowbit(i)];
        draw(x,y,t,true);
        if(dfs(cnt - 1)) return true;
        draw(x,y,t,false);
    }
    return false;
}

int main()
{
    for(int i = 0; i < N; ++ i) map[1 << i] = i;
    for(int i = 0; i < 1 << N; ++ i)
      for(int j = 0; j < N; ++ j)
        ones[i] += i >> j & 1;
    while(cin >> str,str[0] != 'e')
    {
        init();
        int cnt = 0;
        for(int i = 0,k = 0; i < 9; ++ i)
         for(int j = 0; j < 9; ++ j, ++ k)
           if(str[k] != '.')
           {
               int t = str[k] - '1';
               draw(i,j,t,true);
           }
           else cnt ++;
        dfs(cnt);
        puts(str);
    }
}
原文地址:https://www.cnblogs.com/yjyl0098/p/15144308.html