本期题目:5X5方格棋盘难题
在5X5的方格棋盘中(如图),每行、列、斜线(斜线不仅仅包括对角线)最多可以放两个球,如何摆放才能放置最多的球,这样的摆法总共有几种?输出所有的摆法。
要求:用一句SQL实现。
输出格式:从方格棋盘第一行至第5行,每行从第一列到第5列依次输出,0表示不放球,1表示放球。例如:1001000000000000000000000。一行输出一个行号和一个解,按解所在的列字符串顺序从大到小排序。
数据库平台:适用Oracle、MS SQL Sever,版本(Oracle推荐10gr2(包含)以上版本、MS SQL Sever推荐2008版本)
原文见:http://www.itpub.net/thread-1400067-1-1.html
参赛者答案:http://www.itpub.net/thread-1407072-1-1.html
我提交的答案:
with a as ( select 1 c1,1 c2,0 c3,0 c4,0 c5 from dual union all select 1,0,1,0,0 from dual union all select 1,0,0,1,0 from dual union all select 1,0,0,0,1 from dual union all select 0,1,1,0,0 from dual union all select 0,1,0,1,0 from dual union all select 0,1,0,0,1 from dual union all select 0,0,1,1,0 from dual union all select 0,0,1,0,1 from dual union all select 0,0,0,1,1 from dual) select rownum rn,s from ( select r1.c1||r1.c2||r1.c3||r1.c4||r1.c5 ||r2.c1||r2.c2||r2.c3||r2.c4||r2.c5 ||r3.c1||r3.c2||r3.c3||r3.c4||r3.c5 ||r4.c1||r4.c2||r4.c3||r4.c4||r4.c5 ||r5.c1||r5.c2||r5.c3||r5.c4||r5.c5 s from a r1, a r2, a r3, a r4, a r5 where r1.c1+r2.c1+r3.c1+r4.c1+r5.c1<=2 and r1.c2+r2.c2+r3.c2+r4.c2+r5.c2<=2 and r1.c3+r2.c3+r3.c3+r4.c3+r5.c3<=2 and r1.c4+r2.c4+r3.c4+r4.c4+r5.c4<=2 and r1.c5+r2.c5+r3.c5+r4.c5+r5.c5<=2 and r1.c3+r2.c2+r3.c1<=2 and r1.c4+r2.c3+r3.c2+r4.c1<=2 and r1.c5+r2.c4+r3.c3+r4.c2+r5.c1<=2 and r2.c5+r3.c4+r4.c3+r5.c2<=2 and r3.c5+r4.c4+r5.c3<=2 and r3.c1+r4.c2+r5.c3<=2 and r2.c1+r3.c2+r4.c3+r5.c4<=2 and r1.c1+r2.c2+r3.c3+r4.c4+r5.c5<=2 and r1.c2+r2.c3+r3.c4+r4.c5<=2 and r1.c3+r2.c4+r3.c5<=2 order by s desc);
解题思路:
1、先将每行可以放2个棋子的排列组合全部列出,用union all生成记录集。
2、用笛卡尔连接5个表,生成所有行满足要求的排列组合(第行2个棋子)。
3、去除列和斜边不满足要求的记录。
评委意见:
思路和代码简明,结果排序正确,性能良好,写法直截了当,但未说明最大值=10的依据。既然已经预设了每行各有两个球,可以推断每列有且仅有两个球,下面的列判断可以改进为=2而不是<=2。
个人分析:
1、每行都肯定有2个棋子的假定是比较武断的,扣分是应该的,除非自己先用算法或数学方法证明(应该可以证明,但我还不会)。
2、枚举每行都有2个棋子的代码比较难看,扩展性不好,可以改进(第二期改进了)。
3、用笛卡尔连接5个表,假如有行数不是5则需要修改SQL,扩展性不好。
4、SQL整体性能不错,相对其他人的代码简单易懂。
5、没有注释,主要原因是自己认为代码逻辑较简单,评委肯定能看懂,最后还是被扣分了。
由于以上原因最后得分很低,我最喜欢是第3名(TK)的答题,大家有兴趣可以看看。