今日学习内容:搜索
分享一个题目的解题过程(有批注)
数独游戏 洛谷题号https://www.luogu.com.cn/problem/P1784
//数独游戏 洛谷题号https://www.luogu.com.cn/problem/P1784
//date:2021/12/12
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <time.h>
using namespace std;
struct arr{
int x,y;
};
arr bb[100];
#define f(x,y) (x-1)/3*3+(y-1)/3+1//把81个格缩成9个宫格 (新方法)
bool a[20][20],b[20][20],c[20][20],g[100];
int d[20][20],p[20][20],bn[100];
int base=0,ans=-1,sum=0,N;
void print()
{
for (int i=1;i<10;i++){
for (int j=1;j<10;j++)
cout<<d[i][j]<<" ";
cout<<endl;
}
exit(0); //返回
}
int gen()
{
//目的:寻找未知数最少的格(只考虑行列的情况,没考虑宫格)
int x,y,i,j,k,t=7,p;
while (t>0) {
for (i=1;i<82;i++) {
if (g[i]==0){
//x是行 y是列
x= (i-1) / 9 +1 ;
y= (i-1) % 9 +1 ;
k=0;
//在行内寻找
for (j=1;j<10;j++)
if (d[x][j]!=0) k++;
if (k>t) return i;
k=0;
//在行内没寻找到就在列内寻找
for (j=1;j<10;j++)
if (d[j][y]!=0) k++;
if (k>t) return i;
}
}
t--;//如果在行列都没找到就t减一
}
}
void find(int n)
{
int i,j,k,x,y;
if (n>N) print();//如果搜索值超过了未赋值数个数,就返回 (代表全部赋值完了)
else {
k=gen();//返回的值是找到未知数最小的格
x=(k-1) / 9 +1;
y=(k-1) % 9+1;
for (i=1;i<10;i++){
if (a[x][i]==0 && b[y][i]==0 && c[f(x,y)][i]==0){
d[x][y]=i;
a[x][i]=b[y][i]=c[f(x,y)][i]=1;
g[(x-1)*9+(y-1) % 9+1]=1;//把54,55行减去的加回来,还是81
find(n+1);
g[(x-1)*9+(y-1) % 9+1]=0;
a[x][i]=b[y][i]=c[f(x,y)][i]=0;
}
}
}
}
int main()
{
//初始化
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
memset(c,0,sizeof(c));
memset(g,0,sizeof(g));
N=81;//一共81个数
for (int i=1;i<10;i++)
for ( int j =1;j<10;j++) {
cin>>d[i][j];
if (d[i][j]!=0) {
N--;//求出还有多少格没有赋值
g[(i-1)*9+(j-1) % 9+1]=1;
a[i][d[i][j]]=b[j][d[i][j]]=c[f(i,j)][d[i][j]]=1;//标记
}
}
find(1);
return 0;
}
/*
测试样例
0 5 9 3 0 0 2 6 0
0 8 0 0 0 0 9 3 0
0 2 0 0 0 0 0 0 0
0 0 0 0 0 0 0 8 0
0 0 0 0 0 0 0 0 9
9 0 0 0 0 0 1 0 0
0 0 0 8 0 0 0 0 0
5 9 8 0 3 6 0 2 4
2 0 0 0 0 7 8 9 6
*/