TOJ 4972: 數獨 4*4 dfs
阿新 • • 發佈:2018-12-16
描述
預計的週末天氣非常不錯,小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(); } }