数独求解程序
翻到以前写的一个程序。贴出来
优先推理,无法确定的情况下找分支最少的一个去猜,并把当前状态保存,以备将来回溯。
优先推理,无法确定的情况下找分支最少的一个去猜,并把当前状态保存,以备将来回溯。
#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, 0, sizeof(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 &p = 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 &p = 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;
}
#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, 0, sizeof(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 &p = 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 &p = 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;
}