#include "stdio.h"
#include "string.h"
#include<iostream>
using namespace std;
struct node
{
int x,y;
int s[10]; // 对于每个空格,数字i是否可用
int sum; // 对于每个空格,一共可以填入的数字种数
}order[101];
int cnt; // 总空格数
char str[101];
int row[20][20],col[20][20],block[20][20]; //记录第i(行,列,小矩阵)的数字j是否已被占用
int table[101][101]; // 大矩阵
void init()
{
int i,x,y;
memset(row,0,sizeof(row));
memset(col,0,sizeof(col));
memset(block,0,sizeof(block));
cnt=0;
for (i=0;i<81;i++)
{
x=i/9;
y=i%9;
if (str[i]=='.')
{
table[x][y]=0;
order[cnt].x=x;
order[cnt].y=y;
cnt++;
}
else
{
table[x][y]=str[i]-'0';
row[x][str[i]-'0']=1;
col[y][str[i]-'0']=1;
block[x/3*3+y/3][str[i]-'0']=1;
}
}
}
void updata()
{
int x,y,i,j,k;
int oprow[10][10],opcol[10][10],opblock[10][10]; // 记录每行,列,小矩阵中数字k一共有几个可以放置的地方
memset(oprow,0,sizeof(oprow));
memset(opcol,0,sizeof(opcol));
memset(opblock,0,sizeof(opblock));
for (i=0;i<cnt;i++)
{
x=order[i].x;//i这个空位对应的横坐标
y=order[i].y;//i这个空位对应的纵坐标
if (table[x][y]==0)
{
order[i].sum=0;//
memset(order[i].s,0,sizeof(order[i].s));//这个空位i没有数字可以放置
for (k=1;k<=9;k++)
if (row[x][k]==0 && col[y][k]==0 && block[x/3*3+y/3][k]==0)//说明这个i空位放k合适
{
order[i].sum++;//i这个空位可用的数有多少个
order[i].s[k]=1;//在这个空格i,记录这些合适的数字k
oprow[x][k]++;//这一行可能很多个位置可以放k
opcol[y][k]++;//这一列可能很多个位置可以放k
opblock[x/3*3+y/3][k]++;//这个子矩阵可能很多位置可以放k//...
}
}
}
//order[i].s[k],i这个空位能放k这个数字,从而确定是否只能放k这个数字。
//如果只能,那么order[i].s[]其他都为0
for(i=0;i<9;i++)//对于某一行(某一列,某一子矩阵) 如果只有一个空位,且这个空位可以放置k,那么order[i].s[]其他都为0
for (k=1;k<=9;k++)//对于某个数字而言,某一行可以放它的位置只有一个
{
if (oprow[i][k]==1) // 如果第i行,只有一个位置能放置数字k
{
for (j=0;j<cnt;j++)
if (order[j].x==i && table[order[j].x][order[j].y]==0 && order[j].s[k]==1)
{
order[j].sum=1;
memset(order[j].s,0,sizeof(order[j].s));
order[j].s[k]=1; //在这个空位j上就只能存放数字k
break;
}
}
if (opcol[i][k]==1)
{
for (j=0;j<cnt;j++)
if (order[j].y==i && table[order[j].x][order[j].y]==0 && order[j].s[k]==1)
{
order[j].sum=1;
memset(order[j].s,0,sizeof(order[j].s));
order[j].s[k]=1;
break;
}
}
if (opblock[i][k]==1)
{
for (j=0;j<cnt;j++)
if (order[j].x/3*3+order[j].y/3==i && table[order[j].x][order[j].y]==0 && order[j].s[k]==1)
{
order[j].sum=1;
memset(order[j].s,0,sizeof(order[j].s));
order[j].s[k]=1;
break;
}
}
}
}
int getnow()
{
int temp,mark,x,y;
temp=10;
mark=-1;
for (int i=0;i<cnt;i++)
{
x=order[i].x;
y=order[i].y;
if (table[x][y]==0 && order[i].sum<temp)//找所有空位中可填数最少的那个空
{
temp=order[i].sum;
mark=i;
}
}
return mark;
}
int dfs(int w)
{
int now,x,y,k;
if (w==cnt) return 1;
now=getnow();//
if (now==-1) return 0;
x=order[now].x;
y=order[now].y;
for (k=1;k<=9;k++)
if (order[now].s[k])//对于空格now,数字k是否可用,可用>0
{
row[x][k]=1;
col[y][k]=1;
block[x/3*3+y/3][k]=1;
table[x][y]=k;
updata();
if (dfs(w+1)==1) return 1;
row[x][k]=0;
col[y][k]=0;
block[x/3*3+y/3][k]=0;
table[x][y]=0;
updata();
}
return 0;
}
void print()
{
for (int i=0;i<9;i++)
{
for (int j=0;j<9;j++)
printf("%d",table[i][j]);
// cout<<endl;//...
}
printf("\n");
}
int main()
{
int i,j;
while (scanf("%s",str)!=EOF)
{
if (strcmp(str,"end")==0) break;
init();
updata();
if(dfs(0))
print();
}
return 0;
}
POJ3074 sudoku数独
最新推荐文章于 2020-01-31 14:50:58 发布