UVA10957 So Doku Checker

原题链接

题意简述

有若干个数据,每次会给你一个 \(9 \times 9\) 的数独,你需要补全这个数独。其中 \(1\) ~ \(9\) 表示已经确定的数,\(0\) 代表不确定的数,也就是你要填的数。(数独规则请自行百度

如果输入的数独已经不符合规则,输出“Illegal”;如果有唯一解,输出“Unique”;如果有多组解,输出“Ambiguous”;如果无解,输出“Impossible”。(注意是 illegal,只是第一个 i 大写了

题目分析

对于数独一类的问题以及如此小的数据范围(虽然没有说有多少组数据),考虑暴力搜索。

首先特判 Illegal 的情况,对每一行每一列每一个宫格开个桶检查一遍,不符合就直接输出。

然后从 \((1,1)\) 开始搜索,每次搜索到一个点就判断这一列这一行和这一宫格已经有了哪些数,再选择没出现过的数往下搜索。如果没有就返回。

到了 \((9,9)\) 如果符合要求,就说明有一个解。最后判断解的个数就可以了。

由于有数独的规则,搜索的很大一部分其实都被剪枝掉了,所以时间是可以接受的。

注意几点:

  • 输出格式要按题目要求(其实看样例输出就懂了)。

  • 如果到了每一行的尽头,就要到下一行开始搜索(其实搜索顺序没所谓,我这里是一行一行搜)。

  • 如果这个数原本是空的(即为0),那么返回的时候也要赋回0。

  • 每次检查要把桶清零,或者定义局部变量。

代码

#include<bits/stdc++.h>
using namespace std;
namespace my_std{
	#define ll long long 
	#define bl bool
	#define pf printf
	#define pc putchar
	#define fr(i,x,y) for(register ll i=(x);i<=(y);i++)
	#define il inline
	il ll read(){
		ll sum=0,f=1;
		char ch=0;
		while(!isdigit(ch)){
			if(ch=='-') f=-1;
			ch=getchar();
		}
		while(isdigit(ch)){
			sum=sum*10+(ch^48);
			ch=getchar();
		}
		return sum*f;
	}
}
using namespace my_std;
ll a[11][11],cnt=0,ans=0;
bl ck[11],pd;
void dfs(ll x,ll y){
	if(a[x][y]){//如果已经有值 
		if(x==9&&y==9) ans++;
		else if(y==9) dfs(x+1,1);
		else dfs(x,y+1);
		return;
	}
	bl ckk[11];
	memset(ckk,0,sizeof(ckk));
	fr(i,1,9){//检查行/列 
		ckk[a[x][i]]=1;
		ckk[a[i][y]]=1;
	}
	fr(i,3*((x-1)/3)+1,3*((x-1)/3)+3) fr(j,3*((y-1)/3)+1,3*((y-1)/3)+3) ckk[a[i][j]]=1;//检查宫格 
	fr(i,1,9){
		if(!ckk[i]){//判断可以填哪些数 
			a[x][y]=i;
			if(x==9&&y==9) ans++;
			else if(y==9) dfs(x+1,1);
			else dfs(x,y+1);
			a[x][y]=0;//赋回0 
		}
	}
}
int main(){
	while(~scanf("%lld",&a[1][1])){
		ans=0;
		cnt++;
		fr(i,1,9) fr(j,1,9) if(i!=1||j!=1) a[i][j]=read();
		pd=0;
		fr(i,1,9){//检查每一行 
			memset(ck,0,sizeof(ck));
			fr(j,1,9){
				if(ck[a[i][j]]&&a[i][j]) pd=1;
				ck[a[i][j]]=1;
			}
		}
		fr(i,1,9){//检查每一列 
			memset(ck,0,sizeof(ck));
			fr(j,1,9){
				if(ck[a[j][i]]&&a[j][i]) pd=1;
				ck[a[j][i]]=1;
			}
		}
		for(ll i=1;i<=9;i+=3){//检查每一宫格 
			for(ll j=1;j<=9;j+=3){
				memset(ck,0,sizeof(ck));
				fr(ii,i,i+2){
					fr(jj,j,j+2){
						if(ck[a[ii][jj]]&&a[ii][jj]) pd=1;
						ck[a[ii][jj]]=1;
					}
				}
			}
		}
		if(pd){
			pf("Case %lld: Illegal.\n",cnt);
			continue;
		}
		dfs(1,1);
		if(!ans) pf("Case %lld: Impossible.\n",cnt);
		else if(ans==1) pf("Case %lld: Unique.\n",cnt);
		else pf("Case %lld: Ambiguous.\n",cnt);
	}
}
posted @ 2021-09-07 19:59  AFewSuns  阅读(46)  评论(0编辑  收藏  举报