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

传送门


解析:

直接模拟,随手写了一个压位的二进制优化数独,并没有什么用,好处只有搜索才能体现出来吧。。。


代码:

#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;
}

转载于:https://www.cnblogs.com/zxyoi/p/10047105.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
《标准数技巧教程(20210628).pdf》是一本关于标准数游戏技巧的教程。数是一种逻辑思维和推理能力的游戏,对于提高思维能力和解决问题有很大的帮助。 教程首先介绍了数游戏的规则和基本概念。标准数由9x9的方格组成,每个方格内有一个数字,玩家的目标是在每一行、每一列和每个小的九宫格内填入1-9的数字,使得每行、每列和每个小九宫格内的数字都不重复。 教程接着详细介绍了解题的一般方法。首先是观察数初始提供的数字,根据已有的数字来推断其他空格内的数字。其次是使用唯一候选数法,即对于每个空格,找到其可能的候选数字,根据候选数字进行筛选,直至确定唯一数字。然后是使用唯一解法,即对于每个数字,找到其唯一出现的位置,进而确定其他空格的数字。最后是递归法,即通过试错的方式,不断填入数字,直至找到合适的解。 此外,教程还介绍了一些基础的数技巧和策略,如三链数、候选数摒除法、交叉点数等。这些技巧能够帮助玩家更快地解决数难题。 总结来说,《标准数技巧教程(20210628).pdf》是一本详细介绍标准数游戏规则和解题方法的教程,对于喜爱数游戏的玩家,以及希望提升逻辑思维能力和解决问题能力的人来说,是一本非常有价值的参考书。阅读后,读者可以掌握数的基本技巧,并学会运用一些高级策略解决更复杂的数难题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值