LoginSignup
1
1

More than 5 years have passed since last update.

数独ソルバー

Posted at

9×9の数独を二国同盟を使って解こうと思います。

データ構造

候補はそのマスの縦横四角をチェックして入れられる数字です。
例えば1,3,5が入るなら、kouho[1],[3],[5]の値を1、kouho[0]を3、それ以外は0です。

nikoku.cpp
//数字を入れるマス
class masu {
public:
    int number = 0;         //マスに入っている値
    int col, row;           //マスが入っている小区画の位置
    int kouho[9 + 1];   //マスに入りうる候補
};

//全てのマスをまとめたもの
class table {
public:
    masu square[9][9];
};

プログラム

二国同盟とは

二国同盟は、入れるマスが2択に絞られている数字が2つあり、そのマスが全く同じ時、対象のマスはその2つの数字のどちらかが必ず入るという手法です。

[二国同盟-数独の解き方]http://www.sudokugame.org/solv/pairs.php

関数

上記の候補を使って対象となるマスをまず探します。

nikoku.cpp
void rowUnion(table &table){
    //1行目から9行目まで
    for (int i = 0; i < 9; ++i){
        //各数字がどのマスを候補に持つか
        int nitaku[saizu + 1][2] = { 0 };
        for (int k = 1; k < 9 + 1; ++k){
            vector<int> temp;
            for (int j = 0; j < 9; ++j){
                if (table.square[i][j].kouho[k] == 1){
                    temp.push_back(j);
                }
            }
            //候補となるマスが2つしかなければ
            if (temp.size() == 2){
                nitaku[k][0] = temp[0];
                nitaku[k][1] = temp[1];
            }
        }

これで2択に絞られている数字がわかりました。

二国同盟のチェック

nitaku[k][0]とnitaku[k][1]が数字kの入るマスなので、これが一致するかを確認します。

nikoku.cpp
//各数字について
for (int k = 1; k < saizu + 1; ++k){
    //その数字が入るマスが2択であれば
    if (nitaku[k][0] != 0){
        for (int m = k + 1; m < saizu + 1; ++m){
            //同じマスを2択として持つ数字を探す
            if ((nitaku[k][0] == nitaku[m][0]) 
                && (nitaku[k][1] == nitaku[m][1])){
                //2択であるマスをa,bとする
                int a = nitaku[k][0];
                int b = nitaku[k][1];
                //2つのマスの候補を一旦すべて消す
                for (int n = 0; n < saizu + 1; ++n){
                    table.square[i][a].kouho[n] = 0;
                    table.square[i][b].kouho[n] = 0;
                }
                //2つの候補だけの状態にする
                table.square[i][a].kouho[k] = 1;
                table.square[i][a].kouho[m] = 1;
                table.square[i][a].kouho[0] = 2;

                table.square[i][b].kouho[k] = 1;
                table.square[i][b].kouho[m] = 1;
                table.square[i][b].kouho[0] = 2;
            }
        }
    }
}

難問ナンプレを手で解くときは効果的な二国同盟ですが、このコードを使って解いたところかえって遅くなりました。候補が1つしかないマスを確定させるのと、候補が少ないマスから探索するのは速くなったので、二国同盟の出現頻度が少ないのが原因かなと。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1