程序设计展示棋盘上的奥秘(1)
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
程序设计展示棋盘上的奥秘(1)
从高斯八后到矩阵最优搜索
计算机学院杨克昌
0 引言
1 高斯皇后问题
1.1 高斯八皇后问题
1.2 n皇后问题
1.3 n皇后问题求解的图形显示
2 皇后全控棋盘问题
2.1 r个皇后全控n×n棋盘
2.2 回溯求解r个皇后控制n×n棋盘问题
2.3 r个皇后全控n×m棋盘
3 矩阵最优搜索
3.1 矩阵的最大子圈
3.2 矩阵中的最小路径
3.3 迷宫探索
4 简要概括
0引言
1. 常见棋盘
(1)围棋盘(19*19个点)
第13届农心杯世界围棋团体锦标赛第14局(决赛)谢赫战胜李昌镐棋谱(2)中国象棋盘(10*9个点)
(3)五子棋盘(15*15个点)
(4)国际象棋盘(8*8个格)
1996年2月10日至2月17日,国际象棋世界冠军卡斯帕罗夫与IBM开发的“深蓝”计算机对奕。经过艰苦的努力,并施出诱招,卡斯帕罗夫才最终在六盘的对奕中取得四比二的胜绩。
1997年IBM的超级计算机"深蓝"以3.5:2.5的成绩战胜国际象棋冠军卡斯帕罗夫
现在的电脑棋手可每秒搜索300万层棋,甚至可实现每秒算出10亿棋局,比过去电脑搜索快1000倍。这样的电脑棋手能搜索到14~15步棋,它的奕棋能力等级分可达3400分。
2.广义棋盘
从一般某一具体棋盘抽象为一个n行×m列(点、格)的广义棋盘。
当n=m时,为方阵棋盘。如以上的围棋、五子棋、国际象棋都是方阵棋盘。
当n≠m时,为矩阵棋盘。如以上的中国象棋是矩阵棋盘。
探讨棋艺是谢赫、候逸凡等棋坛巨星们的事。本讲座将引导同学们审视与欣赏在棋盘这一方天地发生的一些有趣的故事与精彩,并从程序设计的视角探讨棋盘这一平台上的新奇与奥秘。
1 高斯皇后问题
著名的高斯八皇后问题是借助国际象棋高度抽象出来的一个形象有趣的组合数学问题,实际上是一个有着特殊要求的排列设计。
本节从高斯八皇后问题的枚举求解入手,综合应用回溯或递归求解一般的n皇后问题,进而探讨皇后全控n×n棋盘、及至n×m广义棋盘问题。
1.1 高斯八皇后问题
1. 案例提出
在国际象棋中,皇后可以吃掉同行、同列或同一与棋盘边框成45度角的斜线上的任何棋子,是攻击力最强的。
数学大师高斯(Gauss)于1850年由此引申出著名的八皇后问题:在国际象棋的8×8方格的棋盘上如何放置8个皇后,使得这8个皇后不能相互攻击,即没有任意两个皇后处在同一横排,同一纵列,或同一与棋盘边框成45度角的斜线上。
高斯当时认为有76个解。至1854年在柏林的象棋杂志上不同的作者共发表了40个不同的解。高斯八皇后问题到底有多少个不同的解?
2. 皇后问题解的表示
下图就是高斯八皇后问题的一个解。我们看到,图中的8个皇后既不同行,也不同列,也没有同处一对角线上,即任意两个皇后都不相互攻击。
图1 高斯八皇后问题的一个解
这个解如何简单地表示?
试用一个8位数表示高斯8皇后问题的一个解:8位数的第k个数字为j,表示棋盘上的第k行的第j格放置一个皇后。可知,图1所示的解可表示为27581463。
其次,这一解是如何求得的?高斯八皇后问题共有多少个不同的解?
3. 枚举求解八皇后问题
(1)设置枚举循环
设置枚举a循环,注意到解的范围应为区间[12345678,87654321]。而数字1~8的任意一个排列的数字和为9的倍数,即数字1~8的任意一个排列均为9的倍数,因而枚举循环的枚举范围定为[12345678, 87654321],其循环步长可优化为9。
(2)任两个皇后不允许处在同一横排,同一纵列
要求8位数中数字1~8各出现一次,不能重复。
设置f数组,分离a的8个数字,用f(x)统计a中数字x的个数。若f(1)~f(8)均等于1,即数字1~8在a中各出现1次。否则返回。
(3)任两个皇后不允许处在同一斜线上
设置g数组,若a的第k个数字为x,则g(k)=x。要求解的8位数的第j个数字与第k 个数字的绝对值不等于j-k(设置j>k)。若出现
|g(j)-g(k)|=j-k
表明j与k出现同处在与棋盘边框成45°角的斜线上,则返回。
(4)输出解
在枚举范围内同时通过以上(2)(3)两道筛选的8位数即为一个解,打印输出(每行打印6个解),同时用变量s统计解的个数。
4. 枚举求解8皇后问题程序设计
// 枚举求解高斯8皇后问题
#include
#include
void main()
{int s,k,i,j,t,x,f[9],g[9]; long a,y;
s=0;
printf(" 高斯八皇后问题的解为:\n");
for(a=12345678;a<=87654321;a=a+9) // 步长为9枚举8位数
{y=a;k=0;
for(i=1;i<=8;i++) f[i]=0;
for(k=1;k<=8;k++)
{ x=y%10;f[x]++;
g[k]=x;y=y/10; // 分离a各个数字并用f,g数组统计
}
for(t=0,i=1;i<=8;i++)
if(f[i]!=1) {t=1;break;} // 数字1--8出现不为1次,返回
if(t==1) continue;
for(k=1;k<=7;k++) // 同处在45度角的斜线上,返回
for(j=k+1;j<=8;j++)
if(abs(g[j]-g[k])==j-k)
{t=1;k=7;break;}
if(t==1) continue;
s++; // 输出8皇后问题的解
printf("%ld ",a);