2018.11.07【校内模拟】数独(模拟)

版权声明:转载请声明出处,谢谢配合。 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;
}

猜你喜欢

转载自blog.csdn.net/zxyoi_dreamer/article/details/83829855