数独求解程序

翻到以前写的一个程序。贴出来
优先推理,无法确定的情况下找分支最少的一个去猜,并把当前状态保存,以备将来回溯。
#include <cstdio>
#include 
<cstring>
#include 
<cassert>
#include 
<vector>
#include 
<algorithm>

using namespace std;

struct Node
{
    
char str[9][10];
    
char used[27][10];
    
int rest;
    
int lastx, lasty;
    
int dup;
    Node():dup(
0)
    
{
    }

    
struct Place
    
{
        Place(
int _x, int _y):x(_x), y(_y){}
        
int x, y;
        
bool operator < (const Place &o) const
        
{
            
return x + y * 3 < o.x + o.y * 3;
        }

    }
;
    vector
< Place > validplace[27][9];
    
bool operator < (const Node &o) const
    
{
        
if (rest == o.rest)
            
return dup < o.dup;
        
return rest < o.rest;
    }

    
struct Index
    
{
        Index(
int _i, int _k, int _size):i(_i), k(_k), size(_size){}
        
int i, k, size;
        vector
<Node> ns;
        
bool operator < (const Index &o) const
        
{
            
return size < o.size;
        }

        
void sortnode()
        
{
            sort(ns.begin(), ns.end());
        }

    }
;
    
void buildinfo()
    
{
        
int i, j;
        memset(used, 
0sizeof(used));
        rest 
= 0;
        
for (i = 0; i < 9; i++)
        
{
            
for (j = 0; j < 9; j++)
            
{
                
if (str[i][j] == '0')
                    rest
++, str[i][j] = 0;
                
else
                
{
                    str[i][j] 
-= '0';
                    assert(used[i][str[i][j]] 
== 0 && used[j + 9][str[i][j]] == 0
                     
&& used[i/3 + j/3*3 + 18][str[i][j]] == 0);
                    used[i][str[i][j]] 
= 1;
                    used[j 
+ 9][str[i][j]] = 1;
                    used[i
/3 + j/3*3 + 18][str[i][j]] = 1;
                }

            }

        }

        lastx 
= lasty = -1;
    }

    
void guess(int i, int j, int k)
    
{
        assert(str[i][j] 
== 0);
        str[i][j] 
= k;
        lastx 
= i;
        lasty 
= j;
        assert(used[i][k] 
== 0 && used[j + 9][k] == 0
            
&& used[i/3 + j/3*3 + 18][k] == 0);
        used[i][k] 
= 1;
        used[j 
+ 9][k] = 1;
        used[i
/3 + j/3*3 + 18][k] = 1;
        rest
--;
    }

    
void discursion()
    
{
        
int i, j, k;
        
bool change;
        
// 先进行充分的严格推理
        do
        
{
            change 
= false;
            
for (i = 0; i < 27; i++)
            
{
                
for (j = 0; j < 9; j++)
                    validplace[i][j].clear();
            }

            
for (i = 0; i < 9; i++)
            
{
                
for (j = 0; j < 9; j++)
                
{
                    
if (str[i][j])
                        
continue;
                    
for (k = 1; k <= 9; k++)
                    
{
                        
if (used[i][k] || used[j+9][k] || used[i/3 + j/3*3 + 18][k])
                            
continue;
                        validplace[i][k
-1].push_back(Place(i, j));
                        validplace[j
+9][k-1].push_back(Place(i, j));
                        validplace[i
/3 + j/3*3 + 18][k-1].push_back(Place(i, j));
                    }

                }

            }

            
for (i = 0; i < 27; i++)
            
{
                
for (k = 1; k <= 9; k++)
                
{
                    
if (validplace[i][k - 1].size() != 1)
                        
continue;

                    
const Place &= validplace[i][k - 1].front();
                    guess(p.x, p.y, k);
                    change 
= true;
#ifdef _DEBUG
                    
//show();
#endif
                    
goto End;
                }

            }

            End:
            ;
        }
while(change && rest);
    }

    
void solve()
    
{
        discursion();

        
if (rest == 0)
            
return;

        
int i, k;
        
//选择分支最少的情况优先进行猜测
        vector<Index> best;
        vector
<Node> nextNodes;
        
for (i = 0; i < 27; i++)
        
{
            
for (k = 1; k <= 9; k++)
            
{
                
if (!validplace[i][k - 1].empty())
                
{
                    
//Index idx(i, k, validplace[i][k - 1].size());
                    for (int t = 0; t < validplace[i][k - 1].size(); t++)
                    
{
                        
const Place &= validplace[i][k - 1][t];
                        Node o2(
*this);
                        o2.guess(p.x, p.y, k);
                        o2.discursion();
                        
//idx.ns.push_back(o2);
                        o2.dup = validplace[i][k - 1].size();
                        nextNodes.push_back(o2);
                        
//idx.rest += o2.rest;
                    }

                    
//idx.sortnode();
                    
//best.push_back(idx);
                }

            }

        }

        
//sort(best.begin(), best.end());
        sort(nextNodes.begin(), nextNodes.end());

        
//for (vector<Index>::iterator id = best.begin(); id != best.end(); ++id)
        for (vector<Node>::iterator nd = nextNodes.begin(); nd != nextNodes.end(); ++nd)
        
{
            
//for (int i = 0; i < id->size; i++)
            {
                
//Node &o2 = id->ns[i];
                Node &o2 = *nd;
                o2.solve();
                
if (o2.rest == 0)
                
{
                    
*this = o2;
                    
return;
                }

            }

        }

    }

    
void show() const
    
{
        
int i, j;
        printf(
"rest %d\n", rest);
        
for (i = 0; i < 9; i++)
        
{
            
for (j = 0; j < 9; j++)
            
{
                
if (str[i][j])
                
{
                    
if (i == lastx && j == lasty)
                        printf(
"-%d-", str[i][j]);
                    
else
                        printf(
" %d ", str[i][j]);
                }

                
else
                    printf(
"   ");
            }

            printf(
"\n");
        }

        
//system("pause");
    }

}
;

int main()
{
    Node n;
    
int i, j;
#if 0
    
for (i = 0; i < 9; i++)
    
{
        scanf(
"%s", n.str[i]);
        assert(strlen(n.str[i]) 
== 9);
        
for (j = 0; j < 9; j++)
        
{
            assert(n.str[i][j] 
>= '0' && n.str[i][j] <= '9');
        }

    }

    n.buildinfo();
    n.show();
    n.discursion();
    
if (n.rest == 0)
        n.show();
#else
    
char buf[9*9+1];
    
while(scanf("%s", buf) == 1 && buf[0!= 'e')
    
{
        
for (i = 0; i < 9; i++)
        
{
            
for (j = 0; j < 9; j++)
            
{
                n.str[i][j] 
= buf[i*9+j];
                
if (n.str[i][j] == '.')
                    n.str[i][j] 
= '0';
            }

        }

        n.buildinfo();
        
//n.show();
        n.solve();
        
//n.show();
        for (i = 0; i < 9; i++)
        
{
            
for (j = 0; j < 9; j++)
            
{
                buf[i
*9+j] = n.str[i][j] + '0';
            }

        }

        buf[
81= 0;
        printf(
"%s\n", buf);
    }

#endif
    
return 0;
}

原文地址:https://www.cnblogs.com/kaikai/p/1067850.html