POJ 2676 Sudoku

正月に帰省したとき暇だったので数独Solverを書いてたんだけど、最近POJやってみようかなーと思って眺めていたらこの問題を見つけ、通してみた。

問題

数独を解け!

解法

枝刈り探索。

ソースコード

#include <iostream>
#include <string>
#include <cstring>
#include <vector>

using std::vector;

int const n=9;
int const m=3;
typedef vector<int> vi;
typedef vector<vi> vvi;

namespace solver {
    bool column[n+1][n+1];
    bool raw[n+1][n+1];
    bool block[n+1][n+1];
    vector<vvi> ans;
    vvi g(n,vi(n));

    void rec(int x,int y){
        while(y!=n && g[y][x]){
            x++;
            if(x>=n){
                x=0;y++;
            }
        }
        if(y==n){
            ans.push_back(g);
            return;
        }
        for(int i=1;i<=n;i++){
            if(column[x][i]||raw[y][i]||block[x/m*m+y/m][i]){
                continue;
            }
            column[x][i]=raw[y][i]=block[x/m*m+y/m][i]=true;
            g[y][x]=i;
            rec(x,y);
            if(ans.size())return;
            column[x][i]=raw[y][i]=block[x/m*m+y/m][i]=false;
            g[y][x]=0;
        }
    }

    vector<vvi> solve(vvi const& g_){
        g.assign(n,vi(n,0));
        memset(column,0,sizeof(column));
        memset(raw,0,sizeof(raw));
        memset(block,0,sizeof(block));
        ans.clear();
        for(int y=0;y<n;y++){
            for(int x=0;x<n;x++){
                int t=g_[y][x];
                g[y][x]=t;
                column[x][t]=raw[y][t]=block[x/m*m+y/m][t]=true;
            }
        }
        rec(0,0);
        return ans;
    }
}

int main(){
    using std::cin;
    using std::cout;
    using std::endl;
    int _;cin>>_;
    while(_--){
        vvi g(n,vi(n));
        for(int y=0;y<n;y++){
            std::string s;cin>>s;
            for(int x=0;x<n;x++){
                g[y][x]=s[x]-'0';
            }
        }

        vector<vvi> ans=solver::solve(g);
        for(int y=0;y<n;y++){
            for(int x=0;x<n;x++){
                cout<<ans[0][y][x];
                if(x+1==n)cout<<endl;
            }
        }
    }
}