数独2
请你将一个16x16的数独填写完整,使得每行、每列、每个4x4十六宫格内字母A~P均恰好出现一次。
保证每个输入只有唯一解决方案。
输入格式 输入包含多组测试用例。
每组测试用例包括16行,每行一组字符串,共16个字符串。
第i个字符串表示数独的第i行。
字符串包含字符可能为字母A~P或”-“(表示等待填充)。
测试用例之间用单个空行分隔,输入至文件结尾处终止。
输出格式 对于每个测试用例,均要求保持与输入相同的格式,将填充完成后的数独输出。
每个测试用例输出结束后,输出一个空行。
输入样例: –A----C-----O-I -J–A-B-P-CGF-H- –D--F-I-E----P- -G-EL-H----M-J– ----E----C–G— -I–K-GA-B—E-J D-GP–J-F----A– -E—C-B–DP–O- E–F-M–D--L-K-A -C--------O-I-L- H-P-C–F-A–B— —G-OD—J----H K—J----H-A-P-L –B--P–E--K–A- -H–B--K–FI-C– –F—C–D--H-N- 输出样例: FPAHMJECNLBDKOGI OJMIANBDPKCGFLHE LNDKGFOIJEAHMBPC BGCELKHPOFIMAJDN MFHBELPOACKJGNID CILNKDGAHBMOPEFJ DOGPIHJMFNLECAKB JEKAFCNBGIDPLHOM EBOFPMIJDGHLNKCA NCJDHBAEKMOFIGLP HMPLCGKFIAENBDJO AKIGNODLBPJCEFMH KDEMJIFNCHGAOPBL GLBCDPMHEONKJIAF PHNOBALKMJFIDCEG IAFJOECGLDPBHMNK
本题设计到的算法是dfs,重点在于剪枝我们首先借鉴数独1的思想,每次搜索先遍历可能次数小的位置,初次之外我们还必须进行其他剪枝:
每行、每列、每个16*16宫格都进行剪枝,每次遍历之后若判断当前出现不合法的填写方式,则回溯,若找到某空格有唯一填的形式,则直接进行下一层搜索。
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std
;
const int N
=16;
int state
[N
][N
];
char str
[N
][N
+1];
int ones
[1<<N
],map
[1<<N
];
char bstr
[N
*N
+1][N
][N
+1];
int bstate
[N
*N
+1][N
][N
],bstate2
[N
*N
+1][N
][N
];
inline int lowbit(int k
)
{
return k
& -k
;
}
void draw(int x
,int y
,int c
)
{
str
[x
][y
]='A'+c
;
for(int i
=0;i
<N
;i
++)
{
state
[x
][i
]&=~(1<<c
);
state
[i
][y
]&=~(1<<c
);
}
int sx
=x
/4*4,sy
=y
/4*4;
for(int i
=0;i
<4;i
++)
for(int j
=0;j
<4;j
++)
state
[sx
+i
][sy
+j
]&=~(1<<c
);
state
[x
][y
]=1<<c
;
}
bool
dfs(int cnt
)
{
if(!cnt
)return true
;
int kcnt
=cnt
;
memcpy(bstate
[kcnt
],state
,sizeof state
);
memcpy(bstr
[kcnt
],str
,sizeof str
);
for(int i
=0;i
<N
;i
++)
for(int j
=0;j
<N
;j
++)
if(str
[i
][j
]=='-')
{
if(!state
[i
][j
])
{
memcpy(state
,bstate
[kcnt
],sizeof state
);
memcpy(str
,bstr
[kcnt
],sizeof str
);
return false
;
}
if(ones
[state
[i
][j
]]==1)
{
draw(i
,j
,map
[state
[i
][j
]]);
cnt
--;
}
}
for(int i
=0;i
<N
;i
++)
{
int sor
=0,sand
=(1<<N
)-1;
int drawn
=0;
for(int j
=0;j
<N
;j
++)
{
int s
=state
[i
][j
];
sand
&=~(sor
&s
);
sor
|=s
;
if(str
[i
][j
]!='-')
drawn
|=state
[i
][j
];
}
if(sor
!=(1<<N
)-1)
{
memcpy(state
,bstate
[kcnt
],sizeof state
);
memcpy(str
,bstr
[kcnt
],sizeof str
);
return false
;
}
for(int j
=sand
;j
;j
-=lowbit(j
))
{
int t
=lowbit(j
);
if(!(drawn
&t
))
{
for(int k
=0;k
<N
;k
++)
if(state
[i
][k
]&t
)
{
draw(i
,k
,map
[t
]);
cnt
--;
break;
}
}
}
}
for(int i
=0;i
<N
;i
++)
{
int sor
=0,sand
=(1<<N
)-1;
int drawn
=0;
for(int j
=0;j
<N
;j
++)
{
int s
=state
[j
][i
];
sand
&=~(sor
&s
);
sor
|=s
;
if(str
[j
][i
]!='-')
drawn
|=state
[j
][i
];
}
if(sor
!=(1<<N
)-1)
{
memcpy(state
,bstate
[kcnt
],sizeof state
);
memcpy(str
,bstr
[kcnt
],sizeof str
);
return false
;
}
for(int j
=sand
;j
;j
-=lowbit(j
))
{
int t
=lowbit(j
);
if(!(drawn
&t
))
{
for(int k
=0;k
<N
;k
++)
if(state
[k
][i
]&t
)
{
draw(k
,i
,map
[t
]);
cnt
--;
break;
}
}
}
}
for(int i
=0;i
<N
;i
++)
{
int sor
=0,sand
=(1<<N
)-1;
int drawn
=0;
for(int j
=0;j
<N
;j
++)
{
int sx
=i
/4*4,dx
=j
/4;
int sy
=i
%4*4,dy
=j
%4;
int s
=state
[sx
+dx
][sy
+dy
];
sand
&=~(sor
&s
);
sor
|=s
;
if(str
[sx
+dx
][sy
+dy
]!='-')
drawn
|=state
[sx
+dx
][sy
+dy
];
}
if(sor
!=(1<<N
)-1)
{
memcpy(state
,bstate
[kcnt
],sizeof state
);
memcpy(str
,bstr
[kcnt
],sizeof str
);
return false
;
}
for(int j
=sand
;j
;j
-=lowbit(j
))
{
int t
=lowbit(j
);
if(!(drawn
&t
))
{
for(int k
=0;k
<N
;k
++)
{
int sx
=i
/4*4,dx
=k
/4;
int sy
=i
%4*4,dy
=k
%4;
if(state
[sx
+dx
][sy
+dy
]&t
)
{
draw(sx
+dx
,sy
+dy
,map
[t
]);
cnt
--;
break;
}
}
}
}
}
if(!cnt
)return true
;
int x
,y
,s
=100;
for(int i
=0;i
<N
;i
++)
for(int j
=0;j
<N
;j
++)
if(str
[i
][j
]=='-'&&ones
[state
[i
][j
]]<s
)
{
x
=i
,y
=j
;
s
=ones
[state
[i
][j
]];
}
memcpy(bstate2
[kcnt
],state
,sizeof state
);
for(int i
=state
[x
][y
];i
;i
-=lowbit(i
))
{
memcpy(state
,bstate2
[kcnt
],sizeof state
);
draw(x
,y
,map
[lowbit(i
)]);
if(dfs(cnt
-1))return true
;
}
memcpy(state
,bstate
[kcnt
],sizeof state
);
memcpy(str
,bstr
[kcnt
],sizeof str
);
return false
;
}
int main()
{
for(int i
=0;i
<N
;i
++)
map
[1<<i
]=i
;
for(int i
=1;i
<1<<N
;i
++)
{
for(int j
=i
;j
;j
-=lowbit(j
))
ones
[i
]++;
}
while(cin
>>str
[0])
{
for(int i
=1;i
<N
;i
++)
cin
>>str
[i
];
for(int i
=0;i
<N
;i
++)
for(int j
=0;j
<N
;j
++)
state
[i
][j
]=(1<<N
)-1;
int cnt
=0;
for(int i
=0;i
<N
;i
++)
for(int j
=0;j
<N
;j
++)
if(str
[i
][j
]!='-')
{
draw(i
,j
,str
[i
][j
]-'A');
}
else cnt
++;
dfs(cnt
);
for(int i
=0;i
<N
;i
++)
cout
<<str
[i
]<<endl
;
cout
<<endl
;
}
return 0;
}