标签:国际象棋 include 数学家 count queen
八皇后问题是一个古老而著名的问题,是回溯算法的典型例题。
该问题是19世纪著名的数学家高斯1850年提出:在8×8格的
国际象棋上摆放8个皇后,使其不能相互共计,即任意两个皇后
都不能处于同一行、同一列或同一斜线上,问有多少种摆法?
#include <stdio.h> #define N 8 int count = 0; //答案编号 int queen[N]; //第i(0<=i<N)行的皇后在queen[i]列 int col[N]; //第i列是否可以放queen,可以为1,否则为0 int lu_to_rd[2*N]; //左上(leftup)至右下(rightdown)的斜线上是否可以放queen,可以为1,否则为0 int ld_to_ru[2*N]; //左下(leftdown)至右上是否可以放queen,可以为1,否则为0 void printArray(); //打印答案 int able(int i,int j); //第i行第j列是否是否可以放queen,可以返回1,否则返回0 void recursion(int i); //从第i行开始递归求解 int main(void) { int i; for(i=0;i<N;i++) //初始化 { col[i] = 1; } for(i=0;i<2*N;i++) { lu_to_rd[i] = ld_to_ru[i] = 1; } recursion(0); return 0; } void printArray() { int i,j; printf("----------------------------------\n"); printf("count: %d \n",count++); for(i=0;i<N;i++) { for(j=0;j<8;j++) { if(queen[i]!=j) { printf("_"); } else { printf("Q"); //打印queen } } printf("\n"); } printf("----------------------------------\n"); } int able(int i,int j) { if (col[j] == 1 && lu_to_rd[i+j] == 1 && ld_to_ru[i-j-1+N] == 1) //假如列方向和两个对角线方向上全都可以放queen, { //就返回1 return 1; } return 0; } void recursion(int a) { int i; if(a>=N) //a >= N 说明已经递归到最后一行,输出答案 { printArray(); } else { for(i=0;i<N;i++) { if(able(a,i)) { queen[a] = i; //第i列可以放queen col[i] = 0; //因为第i列已经放了queen,则要设置该列和两个对角线方向上为0 lu_to_rd[a+i] = ld_to_ru[a-i-1+N] = 0; recursion(a+1); //递归到下一行求解 col[i] = 1; //上一层递归结束后要更新第i列的信息 lu_to_rd[a+i] = ld_to_ru[a-i-1+N] = 1 ; } } } }
关于两条斜线上的问题:
一、判断问题
其实判断两个点在不在同一条斜线上,就是判断这两个点是不是属于同一条直线;
利用坐标的思想(x + y = b || x - y = c #两条斜线的倾斜角为45度或135度);
而第i行第j列很容易转换成坐标;例如queen[1] = 2,queen[2] = 1,易得出这两点在同一条斜线上;
二、数组大小问题
8*8的正方形(0,0)(1,0)(0,1).........
会发现由整数点所连起来的倾角为45度的直线一共有13条,但为了判断的方便,我们把(7,0)(0,7)的点也算上;
这样就一共是15条,写简单点就写成了2*N;
本文出自 “一二三四五六七” 博客,请务必保留此出处http://8997342.blog.51cto.com/8987342/1622375
标签:国际象棋 include 数学家 count queen
原文地址:http://8997342.blog.51cto.com/8987342/1622375