版权声明:转载请声明出处,谢谢配合。 https://blog.csdn.net/zxyoi_dreamer/article/details/83829855
传送门
解析:
直接模拟,随手写了一个压位的二进制优化数独,并没有什么用,好处只有搜索才能体现出来吧。。。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const
inline int getint(){
re int num;
re char c;
while(!isdigit(c=gc()));num=c^48;
while(isdigit(c=gc()))num=(num<<1)+(num<<3)+(c^48);
return num;
}
inline char getalpha(){
re char c;
while(!isalpha(c=gc()));
return c;
}
inline void skip(){
while(!isspace(cin.peek()))cin.get();
}
cs int block[10][10]={
{0,0,0,0,0,0,0,0,0,0},
{0,1,1,1,2,2,2,3,3,3},
{0,1,1,1,2,2,2,3,3,3},
{0,1,1,1,2,2,2,3,3,3},
{0,4,4,4,5,5,5,6,6,6},
{0,4,4,4,5,5,5,6,6,6},
{0,4,4,4,5,5,5,6,6,6},
{0,7,7,7,8,8,8,9,9,9},
{0,7,7,7,8,8,8,9,9,9},
{0,7,7,7,8,8,8,9,9,9}
};
struct sudoku{
int row[10],col[10],square[10];
int val[10][10];
void init(){
memset(row,0,sizeof row);
memset(col,0,sizeof col);
memset(square,0,sizeof square);
for(int re i=1;i<=9;++i){
for(int re j=1;j<=9;++j){
if(val[i][j]){
row[i]|=1<<val[i][j];
col[j]|=1<<val[i][j];
square[block[i][j]]|=1<<val[i][j];
}
}
}
}
int *cs operator[](cs int &offset){
return val[offset];
}
cs int *cs operator[](cs int &offset)cs{
return val[offset];
}
bool check(int i,int j,int v){
if(val[i][j])return false;
if(row[i]&(1<<v))return false;
if(col[j]&(1<<v))return false;
if(square[block[i][j]]&(1<<v))return false;
return true;
}
void print(){
puts("+-+-+-+-+-+-+-+-+-+");
for(int re i=1;i<=9;++i){
for(int re j=1;j<=9;++j){
pc('|');
pc(val[i][j]^48);
}
pc('|');pc('\n');
puts("+-+-+-+-+-+-+-+-+-+");
}
}
inline void insert(int i,int j,int v){
val[i][j]=v;
row[i]|=1<<v;
col[j]|=1<<v;
square[block[i][j]]|=1<<v;
}
inline void del(int i,int j){
int v=val[i][j];
val[i][j]=0;
row[i]^=1<<v;
col[j]^=1<<v;
square[block[i][j]]^=1<<v;
}
}s[105];
inline void merge(sudoku &t,cs sudoku &a,cs sudoku &b){
int cnta=0,cntb=0;
for(int re i=1;i<=9;++i){
for(int re j=1;j<=9;++j){
if(a[i][j]&&t.check(i,j,a[i][j])){
++cnta;
t.insert(i,j,a[i][j]);
continue;
}
if(b[i][j]&&t.check(i,j,b[i][j])){
++cntb;
t.insert(i,j,b[i][j]);
continue;
}
}
}
printf("%d %d\n",cnta,cntb);
}
int T;
signed main(){
for(int re i=1;i<=9;++i)
for(int re j=1;j<=9;++j){
s[0][i][j]=getint();
}
s[0].init();
T=getint();
for(int re i=1;i<=T;++i){
sudoku &t=s[i];
char op=getalpha();
switch(op){
case 'I':{
t=s[i-1];
int x=getint(),y=getint(),v=getint();
if(t.check(x,y,v)){
puts("OK!");
t.insert(x,y,v);
break;
}
if(t[x][y])puts("Error!");
else if(t.row[x]&(1<<v))puts("Error:row!");
else if(t.col[y]&(1<<v))puts("Error:column!");
else puts("Error:square!");
break;
}
case 'D':{
t=s[i-1];
int x=getint(),y=getint();
if(!t[x][y])puts("Error!");
else {
puts("OK!");
t.del(x,y);
}
break;
}
case 'Q':{
t=s[i-1];
int x=getint(),y=getint();
if(t[x][y]){puts("Error!");break;}
int sta=t.row[x]|t.col[y]|t.square[block[x][y]];
int cnt=0;
for(int re j=9;j;--j)if(!(sta&(1<<j)))++cnt;
pc(cnt^48);pc('\n');
for(int re j=1;j<=9;++j)if(!(sta&(1<<j)))pc(j^48),pc('\n');
break;
}
case 'M':{
int u=getint(),v=getint();
merge(t,s[u],s[v]);
break;
}
case 'P':{
skip();
t=s[i-1];
t.print();
break;
}
}
}
return 0;
}