我写了一个比较直观的。没有mod/trunc/除法,更好理解。
with chess -- 棋盘,x横轴,y竖轴,Z1对角1,Z2对角2,n是为了更简便访问的
as ( select /*+ materialize */
x.l as x,y.l as y,x.l+y.l as z1,x.l-y.l as z2,x.l+10*y.l as n
from (select level-1 l from dual connect by level <=7) x,
(select level-1 l from dual connect by level <=7)y ),
chess_attack as -- x,y,z Queen所在位置, kx,ky,kn Queen可以攻击到的位置,type 是攻击类型,x横轴,y竖轴,Z1对角1,Z2对角2
(select /*+ materialize */
a.x,a.y,a.n, b.x kx,b.y ky,b.n as kn,'X' as type from chess a, chess b
where a.x=b.x
union all
select a.x,a.y,a.n, b.x kx,b.y ky,b.n as kn,'Y' as type from chess a, chess b
where a.y=b.y
union all
select a.x,a.y,a.n, b.x kx,b.y ky,b.n as kn,'Z1' as type from chess a, chess b
where a.z1=b.z1
union all
select a.x,a.y,a.n, b.x kx,b.y ky,b.n as kn,'Z2' as type from chess a, chess b
where a.z2=b.z2),
chess_4queen as -- 4个Queen的放置位置,分别是 Q#x,Q#y,Q#n
(select /*+ materialize */
q1.x as q1x,q1.y as q1y,q1.n as q1n,
q2.x as q2x,q2.y as q2y,q2.n as q2n,
q3.x as q3x,q3.y as q3y,q3.n as q3n,
q4.x as q4x,q4.y as q4y,q4.n as q4n
from
chess q1,
chess q2,
chess q3,
chess q4
where
q1.x<=4 and q1.y<=4 -- 对称原则,把第一个Queen放在前1/4棋盘。
and q1.x < q2.x and q2.x < q3.x and q3.x < q4.x -- 其他3个Queen依次排开,不同X
and q1.y != q2.y and q1.y != q3.y and q1.y != q4.y -- 不同Y
and q2.y != q3.y and q2.y != q4.y and q3.y != q4.y
and q1.z1 != q2.z1 and q1.z1 != q3.z1 and q1.z1 != q4.z1 -- 不同Z
and q2.z1 != q3.z1 and q2.z1 != q4.z1 and q3.z1 != q4.z1
and q1.z2 != q2.z2 and q1.z2 != q3.z2 and q1.z2 != q4.z2
and q2.z2 != q3.z2 and q2.z2 != q4.z2 and q3.z2 != q4.z2
)
select * from
(
select j.*,
(select count(distinct kn ) -- 4个Queen能攻击到的位置,去除重复攻击点。
from chess_attack
where n in
(j.q1n,j.q2n,j.q3n,j.q4n)) as cnt
from chess_4queen j
) where cnt = 49
10秒出结果
Q1X,Q1Y,Q1N,Q2X,Q2Y,Q2N,Q3X,Q3Y,Q3N,Q4X,Q4Y,Q4N,CNT
0,1,10,1,5,51,3,0,3,4,4,44,49
0,3,30,1,0,1,4,4,44,5,1,15,49
0,3,30,1,6,61,4,2,24,5,5,55,49
1,1,11,2,4,42,5,0,5,6,3,36,49
2,2,22,3,6,63,5,1,15,6,5,56,49
2,4,42,3,0,3,5,5,55,6,1,16,49 |