1.数独是?
数独(Sudoku)是一种逻辑填数字游戏,目标是在9×9的格子中填入数字1至9,满足以下规则:
- 每一行包含1至9的所有数字且不重复。
- 每一列包含1至9的所有数字且不重复。
- 每个3×3的小宫(共9个)包含1至9的所有数字且不重复。
游戏开局时部分格子已预先填入数字(称为“提示数”),玩家需通过逻辑推理填补剩余空格。
2.数独和我
我发现了一道题目:P1784 数独 - 洛谷
我自然而然的萌生出做一个可视化解题代码的想法,后来发现能通过原题的代码加上输出后,速度太慢,于是进行了性能优化。代码如下:
#include <bits/stdc++.h>
#include <windows.h>
using namespace std;
int a[10][10],p,cnt,b[10][10];
struct node{
int x,y,num;
friend bool operator <(node u1,node u2){
return u1.num>u2.num;
}
}a0[100];
bool pri,h[10][10],l[10][10],jgg[10][10];
void resort(int pos){
for(int i=pos;i<=p;i++){
int n;
if(a0[i].x<=3)
n=0;
else if(a0[i].x<=6)
n=3;
else n=6;
if(a0[i].y<=3)
n++;
else if(a0[i].y<=6)
n+=2;
else n+=3;
a0[i].num=0;
for(int j=1;j<=9;j++)
a0[i].num+=(h[a0[i].x][j]||l[a0[i].y][j]||jgg[n][j]);
}
sort(a0+pos,a0+p+1);
}
void dfs(int pos){
if(pos>p){
pri=1;
return;
}
int n;
if(a0[pos].x<=3)
n=0;
else if(a0[pos].x<=6)
n=3;
else n=6;
if(a0[pos].y<=3)
n++;
else if(a0[pos].y<=6)
n+=2;
else n+=3;
int m=-1;
for(int i=1;i<=9;i++){
if(h[a0[pos].x][i]||l[a0[pos].y][i]||jgg[n][i])
continue;
h[a0[pos].x][i]=l[a0[pos].y][i]=jgg[n][i]=1;
a[a0[pos].x][a0[pos].y]=i;
m=++cnt;
cout<<"当("<<a0[pos].x<<','<<a0[pos].y<<")位置为"<<i<<"时("<<m<<"):{\n";
resort(pos+1);
dfs(pos+1);
if(pri)
return;
cout<<"}("<<m<<")\n";
h[a0[pos].x][i]=l[a0[pos].y][i]=jgg[n][i]=0;
resort(pos+1);
}
if(m==-1)
cout<<'('<<a0[pos].x<<','<<a0[pos].y<<")位置没有可行的解。\n";
}
int main(){
cout<<"欢迎使用可解释型数独填充器,请填入9X9矩阵,0表示待定。\n";
for(int i=1;i<=9;i++)
for(int j=1;j<=9;j++){
cin>>a[i][j];
b[i][j]=a[i][j];
int n;
if(i<=3)
n=0;
else if(i<=6)
n=3;
else n=6;
if(j<=3)
n++;
else if(j<=6)
n+=2;
else n+=3;
if(!a[i][j]){
a0[++p].x=i;
a0[p].y=j;
continue;
}
if(h[i][a[i][j]]||l[j][a[i][j]]||jgg[n][a[i][j]]){
cout<<"警告:此矩阵无解!";
getchar();
}
h[i][a[i][j]]=l[j][a[i][j]]=jgg[n][a[i][j]]=1;
}
resort(1);
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cout<<"好的,推理开始。首先";
dfs(1);
cout<<"整图恰好被填满。\n因此,以上是全部过程。结果为:\n";
for(int i=1;i<=9;i++){
for(int j=1;j<=9;j++)
cout<<a[i][j]<<' ';
cout<<'\n';
}
cout<<"复杂分数:"<<cnt;
return 0;
}
中心思路就是暴力的去试数,但是优化的地方在于寻找方案最少的位置进行尝试,大大压缩了时间复杂度,支持大常数的输出。
可以看出,代码长度对于竞赛题目来说过于冗长,如果大佬有改进和进一步优化的方案,或是大家对此项目有自己的感想,欢迎评论区见!
征求:最复杂的数独题目。您可以运行代码,输入您的数独题目,并查看难度分数,争取打破纪录。蒟蒻在评论区静候。
目前记录:
8 0 0 0 0 0 0 0 0
0 0 3 6 0 0 0 0 0
0 7 0 0 9 0 2 0 0
0 5 0 0 0 7 0 0 0
0 0 0 0 4 5 7 0 0
0 0 0 1 0 0 0 3 0
0 0 1 0 0 0 0 6 8
0 0 8 5 0 0 0 1 0
0 9 0 0 0 0 4 0 0
难度分数:9133