1. 程式人生 > >TOJ 4972: 數獨 4*4 dfs

TOJ 4972: 數獨 4*4 dfs

描述

預計的週末天氣非常不錯,小T和小夥伴在滿足的吃完燒烤後,玩起了數獨。所謂數獨就是在N*N的表格上填補數字,使得每行每列每塊上都存在1~N這N個不同的數字。不過這是小T臨時找的表格,所以只有4*4的大小。

對於4*4的表格,它的每行上都應該含有1~4四個數字,每列上也含有1~4四個數字。然後將其分為4份2*2的小塊,每個小塊也含有1~4這4個數字。一個滿足要求的數獨表格如下所示:

 1 2 | 4 3

 3 4 | 2 1

一一一一

 2 3 | 1 4

 4 1 |

 3 2

那麼問題來了,給你一張沒填完的4*4表格,請問你能將它填完嗎?

輸入

輸入第一行包含一個T,代表一共包含T組資料。

每組資料包含四行四列的表格,每個數字之間以空格隔開。其中Aij代表第i行第j列的數字,如果Aij=?則說明該處還沒有填上數字。

每組資料之間含有一個空行。

保證Aij∈{1,2,3,4,?}。

輸出

每組資料輸出佔一行。

如果表格可以被填滿則輸出Yes,否則輸出No。

具體格式見樣例。

樣例輸入

3
1 ? ? 3
? ? 2 1
2 3 ? ?
4 ? 3 2

1 ? ? 4
? 1 ? ?
2 ? ? ?
? 4 ? ?

1 ? 4 3
? 2 ? ?
2 1 ? ?
4 ? ? 2

樣例輸出

Case #1: Yes
Case #2: No
Case #3: No

數獨規則:橫向,縱向,2*2的小方格里,1-4各出現一次。(2*(i/2)+j/2是計算在第幾個小方格里)

題意:判斷可否完成數獨,dfs中如果可以走到最後(flag=1)說明可行。

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<iostream>
#include<string>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
#include<vector>
using namespace std;
#define inf 0x3f3f3f3f
#define LL long long
int a[20][20],flag;
int r[20][20],l[20][20],s[20][20];//r行 l列 s小方陣 
void dfs(int i,int j)
{
	if(i==4&&j==0)
	flag=1;	
	else
	{
		if(a[i][j]!=0)
		{
			if(j<3)
			dfs(i,j+1);
			else
			dfs(i+1,0);
		}
		else
		{
			for(int k=1;k<=4;k++)
			{
				if(!r[i][k]&&!l[j][k]&&!s[2*(i/2)+j/2][k])
				{
					a[i][j]=k;
					r[i][k]=1;
					l[j][k]=1;
					s[2*(i/2)+j/2][k]=1;
					if(j<3)
					dfs(i,j+1);
					else
					dfs(i+1,0);
					if(flag)return;
					//回溯重置 
					a[i][j]=0;
					r[i][k]=0;
					l[j][k]=0;
					s[2*(i/2)+j/2][k]=0;
				}
			}
		}
	}
}
int main()
{
	int t,i,j,o=1;
	char aa;
	scanf("%d",&t);
	while(t--)
	{
		memset(r,0,sizeof r);
		memset(l,0,sizeof l);		
		memset(s,0,sizeof s);
		for(i=0;i<4;i++)
		{
			for(j=0;j<4;j++)
			{
				getchar();
				scanf("%c",&aa);
				if(aa=='?')
				a[i][j]=0;
				else
				a[i][j]=aa-'0';								
				if(a[i][j])
				{
					r[i][a[i][j]]=1;
					l[j][a[i][j]]=1;
					s[2*(i/2)+j/2][a[i][j]]=1;
				}
			}
		}			
		flag=0;
		dfs(0,0);
		if(flag)
		printf("Case #%d: Yes\n",o++);
		else
		printf("Case #%d: No\n",o++);
		getchar();
	}
}