数独合理吗?

题目链接

题目描述

众所周知,数独是一款简单上手(划掉)且极易打发时间的游戏,fishfloss喜欢玩数独,虽然自己很菜。
数独的具体规则是这样的:
需要根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行、每一列、每一宫(3x3)内的数字均含1-9并不重复。
例如 :
1 2 3 4 5 6 7 8 9
4 5 6 7 8 9 1 2 3
7 8 9 1 2 3 4 5 6
2 3 1 5 6 4 8 9 7
5 6 4 8 9 7 2 3 1
8 9 7 2 3 1 5 6 4
3 1 2 6 4 5 9 7 8
6 4 5 9 7 8 3 1 2
9 7 8 3 1 2 6 4 5
就是一个合法的数独的解

1 2 3 4 5 6 7 8 9
4 5 6 7 8 9 1 2 3
7 8 9 1 2 3 4 5 6
2 3 1 5 6 4 8 9 7
5 6 4 8 9 7 2 3 1
8 9 7 2 3 1 5 6 4
3 1 2 6 4 5 9 7 8
6 4 5 9 7 8 3 1 2
9 7 8 3 1 2 6 4 4
则不是
那么下面给出数独盘面,来判断一下它是否是数独的合法解吧

输入描述:

输入共9行,每行9个数,代表数独盘面

输出描述:

一行,如果输入是数独的合法解,则输出YES
反之输出NO

示例1

输入

1 2 3 4 5 6 7 8 9
4 5 6 7 8 9 1 2 3
7 8 9 1 2 3 4 5 6
2 3 1 5 6 4 8 9 7
5 6 4 8 9 7 2 3 1
8 9 7 2 3 1 5 6 4
3 1 2 6 4 5 9 7 8
6 4 5 9 7 8 3 1 2
9 7 8 3 1 2 6 4 5

输出

YES

示例2

输入

1 2 3 4 5 6 7 8 9
4 5 6 7 8 9 1 2 3
7 8 9 1 2 3 4 5 6
2 3 1 5 6 4 8 9 7
5 6 4 8 9 7 2 3 1
8 9 7 2 3 1 5 6 4
3 1 2 6 4 5 9 7 8
6 4 5 9 7 8 3 1 2
9 7 8 3 1 2 6 4 4
输出

NO
说明
对于宫9,行9及列9,显然有重复的4,故不满足合法解

解题思路:

每一行、每一列、每一宫都不可以有重复的数字,那么可以用计数排序的方法对其进行判断。对行与列的判断比较简单,行的判断甚至可以一边输入一边判断,对列的判断只要交换一下输入的顺序即可。对每一宫的判断是这道题的难点,但是其实想清楚就很简单了。我的做法是将行与列的输入分成三份,在这基础上在写两个for循环进行输入判断。

需要注意的是,用于判断的数组每次判断完之后需要清空,为洗一次判断做准备。

代码如下:

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int a[9][9];
int main()
{
	int i,j,k;
	int flag=0;
	int b[10];
	memset(b,0,sizeof(b));
	//输入+判断每一行
	for(i=0;i<9;i++){
		for(j=0;j<9;j++){
			cin>>a[i][j];
			b[a[i][j]]++;
		}
		for(k=1;k<10;k++){
			if(b[k]!=1){
				flag=1;
				break;
			}
		}
		memset(b,0,sizeof(b));
	}
	//判断每一列
	for(j=0;j<9;j++){
		for(i=0;i<9;i++) b[a[i][j]]++;
		
		for(k=1;k<10;k++){
			if(b[k]!=1){
				flag=1;
				break;
			}
		}
		memset(b,0,sizeof(b));
	}
	//判断每一宫
	for(i=0;i<9;i=i+3){
		for(j=0;j<9;j=j+3){
			//对每一宫内的数判断
			for(int i2=i;i2<i+3;i2++){
				for(int j2=j;j2<j+3;j2++){
					b[a[i2][j2]]++;
				}
			}
			for(k=1;k<10;k++){
				if(b[k]!=1){
					flag=1;
					break;
				}
			}
			memset(b,0,sizeof(b));
			if(flag==1)break;
		}
		if(flag==1)break;
	}
	
	if(flag==1)cout<<"NO"<<endl;
	else cout<<"YES"<<endl;
	
	return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值