- 数独显然是一个0-1规划问题.
- 虽然这个什么凸分析还是啥的分析有这个优化的方法,但是,你DFS也不是完全一点不可能的对吧.
- 嗯,既然这样的话,我们就要去解决这样一个更细致的问题了.数独这个问题他的解的存在性,唯一性怎么样.
- 当然,已经有结论了,一个9*9的数独至少要给出17个值才能约束出一个唯一确定的解
- 我们的目的是什么呢?
- 嗯,好问题,实在不行就调研吧......
- 16个条件时,解的多样性等等等
- 论文已经给出了,我们要做的事情就是先写一点点代码.
Lingo解决数独问题
model:
sets:
number/1..9/;
line/1..9/;
col/1..9/;
link(line,col,number):x;
endsets
data:
@text("ans.txt")=x;
enddata
x(1,1,1) = 1;
x(1,6,7) = 1;
x(1,8,9) = 1;
x(2,2,3) = 1;
x(2,5,2) = 1;
x(2,9,8) = 1;
x(3,3,9) = 1;
x(3,4,6) = 1;
x(3,7,5) = 1;
x(4,3,5) = 1;
x(4,4,3) = 1;
x(4,7,9) = 1;
x(5,2,1) = 1;
x(5,5,8) = 1;
x(5,9,2) = 1;
x(6,6,4) = 1;
x(7,1,3) = 1;
x(7,8,1) = 1;
x(8,2,4) = 1;
x(8,9,7) = 1;
x(9,3,7) = 1;
x(9,7,3) = 1;
@for(line(i):@for(col(j):@sum(number(k):x(i,j,k))=1));
@for(line(i):@for(number(k):@sum(col(j):x(i,j,k))=1));
@for(col(j):@for(number(k):@sum(line(i):x(i,j,k))=1));
@for(number(k):@sum(line(i)|i#GE#1#and#i#LE#3:@sum(col(j)|j#GE#1#and#j#LE#3:x(i,j,k)))=1);
@for(number(k):@sum(line(i)|i#GE#1#and#i#LE#3:@sum(col(j)|j#GE#4#and#j#LE#6:x(i,j,k)))=1);
@for(number(k):@sum(line(i)|i#GE#1#and#i#LE#3:@sum(col(j)|j#GE#7#and#j#LE#9:x(i,j,k)))=1);
@for(number(k):@sum(line(i)|i#GE#4#and#i#LE#6:@sum(col(j)|j#GE#1#and#j#LE#3:x(i,j,k)))=1);
@for(number(k):@sum(line(i)|i#GE#4#and#i#LE#6:@sum(col(j)|j#GE#4#and#j#LE#6:x(i,j,k)))=1);
@for(number(k):@sum(line(i)|i#GE#4#and#i#LE#6:@sum(col(j)|j#GE#7#and#j#LE#9:x(i,j,k)))=1);
@for(number(k):@sum(line(i)|i#GE#7#and#i#LE#9:@sum(col(j)|j#GE#1#and#j#LE#3:x(i,j,k)))=1);
@for(number(k):@sum(line(i)|i#GE#7#and#i#LE#9:@sum(col(j)|j#GE#4#and#j#LE#6:x(i,j,k)))=1);
@for(number(k):@sum(line(i)|i#GE#7#and#i#LE#9:@sum(col(j)|j#GE#7#and#j#LE#9:x(i,j,k)))=1);
@for(link(i,j,k):@bin(x(i,j,k)));
end
读取与验证
f = open("ans.txt")
F = f.readlines()
F = [int(F[i].split(" ")[-1][0]) for i in range(729)]
def check(result):
flag = 1
for i in range(9):
flag = (len(set([result[i*9+j] for j in range(9)])) == 9)
if not flag:
print("第"+str(i+1)+"行不满足条件")
return False
for i in range(9):
flag = (len(set([result[i+9*j] for j in range(9)])) == 9)
if not flag:
print("第"+str(j+1)+"列不满足条件")
return False
for k in range(3):
for l in range(3):
block = ""
for i in range(3):
for j in range(3):
block += result[9*(3*k+i)+(3*l+j)]
flag = (len(set(block)) == 9)
if not flag:
print("("+str(k+1)+","+str(l+1)+")"+"个块不满足条件")
return False
return True
count = 0
result,result0 = "",""
for i in range(81):
for j in range(9):
if F[i*9+j] == 1:
result += (str(j+1))
assert(len(result)==81),"结果总数不是81个"
##result = list(result)
##result[9] = 1
##r = ""
##for i in result:
## r += str(i)
##result = r
if check(result):
for i in range(9):
result0 += (result[i*9:(1+i)*9]+"\n")
print(result0)
C++ DFS
- 显然,我们不想看到我们只能用 Lingo 这样不太方便的方法。
- 我们用深度优先简单的搜索一下这个数独问题的答案
#include<iostream>
#include<fstream>
using namespace std;
typedef int Board[9][9];
int count=0;
void initial(Board board);
void output(Board board);
bool completed(Board board);
bool check(Board board,int i,int j,int target);
void solve(Board board);
ofstream ans("answer.txt");
int main()
{
ans.open("answer.txt",ios::out);
ans << "all answer!";
ans.close();
Board board;
initial(board);
solve(board);
if (!completed(board))
{
cout << "the number of solutions:";
cout << count << endl;
}
return 0;
}
void initial(Board board)
{
board[0][0] = 1;
board[0][1] = 2;
board[0][2] = 0;
board[0][3] = 5;
board[0][4] = 0;
board[0][5] = 0;
board[0][6] = 0;
board[0][7] = 0;
board[0][8] = 0;
board[1][0] = 0;
board[1][1] = 0;
board[1][2] = 0;
board[1][3] = 0;
board[1][4] = 9;
board[1][5] = 0;
board[1][6] = 2;
board[1][7] = 0;
board[1][8] = 0;
board[2][0] = 0;
board[2][1] = 5;
board[2][2] = 0;
board[2][3] = 0;
board[2][4] = 0;
board[2][5] = 2;
board[2][6] = 0;
board[2][7] = 0;
board[2][8] = 0;
board[3][0] = 7;
board[3][1] = 0;
board[3][2] = 5;
board[3][3] = 0;
board[3][4] = 0;
board[3][5] = 0;
board[3][6] = 0;
board[3][7] = 0;
board[3][8] = 9;
board[4][0] = 0;
board[4][1] = 4;
board[4][2] = 0;
board[4][3] = 0;
board[4][4] = 0;
board[4][5] = 0;
board[4][6] = 0;
board[4][7] = 2;
board[4][8] = 0;
board[5][0] = 6;
board[5][1] = 0;
board[5][2] = 0;
board[5][3] = 0;
board[5][4] = 0;
board[5][5] = 0;
board[5][6] = 0;
board[5][7] = 0;
board[5][8] = 0;
board[6][0] = 0;
board[6][1] = 0;
board[6][2] = 0;
board[6][3] = 2;
board[6][4] = 0;
board[6][5] = 0;
board[6][6] = 0;
board[6][7] = 1;
board[6][8] = 0;
board[7][0] = 0;
board[7][1] = 0;
board[7][2] = 8;
board[7][3] = 0;
board[7][4] = 4;
board[7][5] = 0;
board[7][6] = 0;
board[7][7] = 3;
board[7][8] = 0;
board[8][0] = 0;
board[8][1] = 0;
board[8][2] = 0;
board[8][3] = 7;
board[8][4] = 0;
board[8][5] = 1;
board[8][6] = 6;
board[8][7] = 0;
board[8][8] = 4;
}
void output(Board board)
{
cout << "============\n";
ans.open("answer.txt",ios::app);
for(int i=0;i<9;i++)
{
for(int j=0;j<9;j++)
{
ans << board[i][j];
}
}
ans << "\n";
ans.close();
for(int i=0;i<9;i++)
{
for(int j=0;j<9;j++)
{
cout << board[i][j] << " ";
}
cout << endl;
}
}
bool completed(Board board)
{
for(int i=0;i<9;i++)
{
for(int j=0;j<9;j++)
{
if(board[i][j]==0)
{
return false;
}
}
}
return true;
}
bool check(Board board,int i,int j,int target)
{
//行,列检验
for (int m=0;m<9;m++)
{
if(board[i][m]==target || board[m][j]==target)
{
return false;
}
}
//block 检验
int x0 = (i/3)*3,y0 = (j/3)*3;
for(int p=0;p<3;p++)
{
for (int q=0;q<3;q++)
{
if (board[x0+p][y0+q]==target)
{
return false;
}
}
}
return true;
}
void solve(Board board)
{
for(int i=0;i<9;i++)
{
for(int j=0;j<9;j++)
{
if(board[i][j]==0)
{
for(int k=1;k<10;k++)
{
if (check(board,i,j,k))
{
board[i][j] = k;
solve(board);
if (completed(board))
{
output(board);
count++;
}
board[i][j] = 0;
}
}
return ;
//只要从一个0元素开始即可,没必要再来一次。
//解的相对唯一性还是啥的。
}
}
}
}
至少总结一点吧:Lingo也没有那么快,有的时候。。
大型线性稀疏系统
数独很明显是一个大型的线性稀疏系统,我们怎么解一个大型线性稀疏系统呢?