11月5日上午T2

数独是一个有趣的游戏。你需要在一个9×9的矩阵中的每个格子中填入1−91 - 919的数字,使得没有两个相同的数字填入同一行、同一列或同一个九宫格中。

整个矩阵被划分为999个九宫格,若两个格子同时在最左三列、最右三列或中间三列,且同时在最左三行、最右三行或中间三行,则这两个格子在同一九宫格中。

如果两个相同的数同行、同列或同九宫格,则构成一对冲突。如下列状态中,两个111在同一行中,两个222在同一列中,两个333在同一九宫格中,分别是三对冲突;但两个444不是一对冲突。

现在有一个数独的初始状态,出题人想对其进行一些修改和询问操作。需要注意:在操作时,初始状态中的数也可以被删除或者合并时被替换。

1.向目前状态中的指定位置填入一个数:但有可能这个位置已经有一个数了,此时你需要输出一行Error!Error!Error!,然后不进行这次修改操作;在指定的这个位置没有数的情况下,这个数已经与之前存在的在同一行、列或九宫格中的数构成冲突,此时,你需要按照行、列、九宫格的顺序,找到第一种冲突的情况,输出一行Error:row!Error:row!Error:row!,Error:column!Error:column!Error:column!或Error:square!Error:square!Error:square!,然后不进行这次修改操作;否则,你需要输出OK!,并在指定位置填入该数。

2.删除目前状态中的一个位置上的数:若这个位置没有数字,此时你需要输出一行Error!Error!Error!,然后不进行任何操作;否则你需要输出一行OK!OK!OK!,并将该位置的数删除。

3.查询目前状态中的某个位置能填入多少种数字;若被查询的位置已经有数字了,你需要输出一行Error!Error!Error!;否则,输出一行一个整数nnn表示能填入的数字个数,随后n行每行一个整数,按照从小到大的顺序输出能填入的数字。 4.将之前的第iii次操作后的数独状态和第jjj次操作后的数独状态进行合并,作为当前状态。需要注意:对于所有的555种操作,包括但不限于出现Error!Error!Error!或是没有进行任何修改,均被算作一次操作。合并时以行为第一关键字,列为第二关键字的顺序依次考虑每个格子,若第iii次操作后的数独状态中该位置有数且不会与之前冲突则优先填入;否则,在不会与之前冲突的情况下,填入第jjj次操作后的数独状态中该位置的数。若均没有数字或均与本次合并中已填入的数字冲突,则不填入任何数。输出一行,包含空格隔开的两个整数,表示最终的结果中有多少数字来自第iii次操作后的数独状态中,多少来自第jjj次操作后的数独状态中。

5.查询整个数独的状态,你需要使用方阵格式将整个数独目前的状态输出。方阵格式是一个19×19的二维字符数组,具体格式如下,其中用000表示该位置还未填入数字。

+-+-+-+-+-+-+-+-+-+
|0|0|0|0|0|0|0|0|0|
+-+-+-+-+-+-+-+-+-+
|0|0|0|0|0|0|0|0|0|
+-+-+-+-+-+-+-+-+-+
|0|0|0|0|0|0|0|0|0|
+-+-+-+-+-+-+-+-+-+
|0|0|0|0|0|0|0|0|0|
+-+-+-+-+-+-+-+-+-+
|0|0|0|0|0|0|0|0|0|
+-+-+-+-+-+-+-+-+-+
|5|7|0|0|0|0|0|0|0|
+-+-+-+-+-+-+-+-+-+
|0|0|0|0|7|1|0|0|0|
+-+-+-+-+-+-+-+-+-+
|0|0|0|0|0|0|0|0|0|
+-+-+-+-+-+-+-+-+-+
|9|8|7|6|5|4|3|2|1|
+-+-+-+-+-+-+-+-+-+


这题调了一个来小时,坐的后背疼,好在Ac了


#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>
using namespace std;
int a[105][12][12],T,hav[12];
char si[25];
void Print(int now){
	for(int i=1;i<=9;i++){
		printf("+-+-+-+-+-+-+-+-+-+\n");
		for(int j=1;j<=9;j++)
			printf("|%d",a[now][i][j]);
		printf("|\n");
	}
	printf("+-+-+-+-+-+-+-+-+-+\n");
}
void cop(int now){
	for(int i=1;i<=9;i++)
		for(int j=1;j<=9;j++)
			a[now][i][j]=a[now-1][i][j];
}
void add(int x,int y,int k,int now){
	if(a[now][x][y]){printf("Error!\n");return;}
	for(int i=1;i<=9;i++)
		if(a[now][x][i]==k){
			printf("Error:row!\n");
			return;
		}
	for(int i=1;i<=9;i++)
		if(a[now][i][y]==k){
			printf("Error:column!\n");
			return ;
		}
	int s,t;
	if(x%3)
		s=(x/3)*3+1;
	else s=((x/3)-1)*3+1;
	if(y%3)
		t=(y/3)*3+1;
	else t=((y/3)-1)*3+1;
	for(int i=0;i<=2;i++)
		for(int j=0;j<=2;j++){
			if(a[now][s+i][t+j]==k){
				printf("Error:square!\n");
				return;
			}
		}
	a[now][x][y]=k;
	printf("OK!\n");
}
void del(int x,int y,int now){
	if(a[now][x][y]==0){
		printf("Error!\n");
		return;
	}
	a[now][x][y]=0;
	printf("OK!\n");
}
void Query(int x,int y,int now){
	if(a[now][x][y]){
		printf("Error!\n");
		return;
	}
	memset(hav,0,sizeof(hav));
	for(int i=1;i<=9;i++)
		hav[a[now][x][i]]=hav[a[now][i][y]]=1;
	int s,t;
	if(x%3)
		s=(x/3)*3+1;
	else s=((x/3)-1)*3+1;
	if(y%3)
		t=(y/3)*3+1;
	else t=((y/3)-1)*3+1;
	for(int i=0;i<=2;i++)
		for(int j=0;j<=2;j++)
			hav[a[now][s+i][t+j]]=1;
	int ans=0;
	for(int i=1;i<=9;i++){
		if(hav[i]==0) ans++;
	}
	printf("%d\n",ans);
	for(int i=1;i<=9;i++)
		if(hav[i]==0)
			printf("%d\n",i);
}
void Merege(int x,int y,int now){
	int ans1=0,ans2=0;
	for(int i=1;i<=9;i++)
		for(int j=1;j<=9;j++)
			a[now][i][j]=0;
	for(int i=1;i<=9;i++)
		for(int j=1;j<=9;j++){
			//printf("0\n");
			if(a[x][i][j]==0&&a[y][i][j]==0) continue;
			int flag=0;
			for(int k=1;k<=9;k++)
				if(a[now][i][k]==a[x][i][j]) flag=1;
			for(int k=1;k<=9;k++)
				if(a[now][k][j]==a[x][i][j]) flag=1;
			int s,t;
			if(i%3)
				s=(i/3)*3+1;
			else s=((i/3)-1)*3+1;
			if(j%3)
				t=(j/3)*3+1;
			else t=((j/3)-1)*3+1;
			//printf("0\n");
			for(int k=0;k<=2;k++)
				for(int l=0;l<=2;l++)
					if(a[now][s+k][t+l]==a[x][i][j]) flag=1;
			if(!flag){
				ans1++;
				a[now][i][j]=a[x][i][j];
				continue;
			}
			flag=0;
			for(int k=1;k<=9;k++)
				if(a[now][i][k]==a[y][i][j]) flag=1;
			for(int k=1;k<=9;k++)
				if(a[now][k][j]==a[y][i][j]) flag=1;
			for(int k=0;k<=2;k++)
				for(int l=0;l<=2;l++)
					if(a[now][s+k][t+l]==a[y][i][j]) flag=1;
			if(!flag) {a[now][i][j]=a[y][i][j];ans2++;}
		}
	printf("%d %d\n",ans1,ans2);
}
int main(){
	freopen("sudoku.in","r",stdin);
	freopen("sudoku.out","w",stdout);
	for(int i=1;i<=19;i++){
		scanf("%s",si+1);
		if(i&1) continue;
		for(int j=1;j<=19;j++){
			if((j&1)) continue;
			a[0][i/2][j/2]=si[j]-'0'; 
		}
	}
	scanf("%d",&T);
	for(int i=1;i<=T;i++){
		int x,y,k;
		string s;
		cin>>s;
		cop(i);
		if(s=="Insert"){
			scanf("%d%d%d",&x,&y,&k);
			add(x,y,k,i);
		}
		if(s=="Delete"){
			scanf("%d%d",&x,&y);
			del(x,y,i);
		}
		if(s=="Query"){
			scanf("%d%d",&x,&y);
			Query(x,y,i);
		}
		if(s=="Merge"){
			scanf("%d%d",&x,&y);
			Merege(x,y,i);
		}
		if(s=="Print"){
			Print(i);
		}
	}
	return 0;
}

  

 

转载于:https://www.cnblogs.com/NGUalexzhang/p/9908048.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值