Algorlthm gosslp:八皇后问题浅谈
来源:互联网 发布:寝室管理系统数据库 编辑:程序博客网 时间:2024/05/01 09:49
八皇后
8*8的棋盘上放八个皇后棋子,要求在纵行,竖行和斜行的八个方向上都不能有两个以上的皇后。1970和1971年,E.W.Dijkstra与N.Wirth曾用这个问题讲解程序设计技巧,淡然,像我这码农级程序员很难理解怎样应用到程序设计技巧中,现阶段只管理解问题的解决方法。
八皇后问题主要使用递归求解,然而如何减少递归次数呢?
在每次递归时,不必要所有的都检查过,例如若某列检查过,该列的其他格子就不在检查了,这个方法称为分支修剪。
程序中风别在横竖八个地方和斜方向15个地方做了标记,若有皇后则递归返回。本人觉得斜方向的标记控制和递归的调用时问题的精华。
C语言实现:
#include<stdio.h>#include<stdlib.h>#define N 8int column[N+1];int rup[2*N+1];int lup[2*N+1];int queen[N+1]={0};int num;void backtrack(int);int main(void){int i;num = 0;
for(i=1;i<=N;i++)
column[i] = 1;for(i=1;i<=2*N;i++)rup[i] = lup[i] =1;backtrack(1);return 0;}void showAnswer(){int x,y;printf("\n解答%d\n",++num);for(y=1;y<=N;y++){for(x=1;x<=N;x++){if(queen[y]==x){printf(" Q");}else{printf(" .");}}printf("\n");}}void backtrack(int i){int j;if(i>N){showAnswer();}else{for(j= 1;j<=N;j++){if(column[j] == 1&&lup[i-j+N] == 1){queen[i] = j;column[j] = rup[i+j] = lup[i-j+N] = 0;backtrack(i+1);column[j] = rup[i+j] = lup[i-j+N] = 1;}}}}
问题描述:
要求:
算法思想:
代码如下:
* n后问题求解
************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <conio.h>
#define MAXNUMBER 20
//判断当前得到的解向量是否满足问题的解
bool place_queen(int x[],int k)
{
int i;
for(i=1;i<k;i++)
{
if((x[i]==x[k]) || (abs(x[i]-x[k])==abs(i-k)))
return false;
}
return true;
}
//将结果简单信息打印到屏幕
void output_queens(int x[],int n)
{
for(int i=1;i<=n;i++)
printf("%3d",x[i]);
printf("");
}
//将结果详细信息写入文件
void output_queens(FILE *fp,int number,int x[],int n)
{
fprintf(fp,"solution %d:",number);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(j==x[i])
fprintf(fp,"1 ");
else
fprintf(fp,"0 ");
}
fprintf(fp,"");
}
fprintf(fp,"");
}
/************************************************************************
* n后问题求解
* input : n, the number of queens
* output : the vector of solution, X
************************************************************************/
int n_queens(FILE *fp,int n,int x[])
{
int nCount=0; //解个数
int k=1; //先处理第1个皇后
x[1]=0;
while(k>0)
{
x[k]=x[k]+1;//在当前列加1的位置开始搜索
while(x[k]<=n && !place_queen(x,k)) //当前列位置是否满足条件
x[k]=x[k]+1; //不满足,继续搜索下一列位置
if(x[k]<=n) //若存在满足条件的列
{
if(k==n)//是最后一个皇后,则得到一个最终解
{
//break; //此处若break,则只能得到一个解
nCount++;
output_queens(x,n); //输出
output_queens(fp,nCount,x,n);
}
else //否则,处理下一个皇后,即第 k+1 个皇后
{
k++;
x[k]=0;
}
}
else //若不存在满足条件的列,则回溯
{
x[k]=0; //第k个皇后复位为0
k--; //回溯到前一个皇后
}
}
return nCount;
}
int main()
{
int n=8,x[MAXNUMBER]={0};
FILE *fp=fopen("8皇后问题的解.txt","w");
if(fp==NULL)
{
printf("can not wirte file!");
exit(0);
}
printf("the queens are placed on the coloums :");
//求解并写入文件
int nCount=n_queens(fp,n,x);
printf("there are %d solutions!",nCount);
fclose(fp);
getch();
return 0;
}
与其他方法对比:
#include <stdio.h>
#include <stdlib.h>
#define max 8
int queen[max], sum=0; /* max为棋盘最大坐标 */
void show() /* 输出所有皇后的坐标 */
{
int i;
printf("(");
for(i = 0; i < max; i++)
{
printf(" %d", queen[i]);
}
printf(")\n");
sum++;
}
int PLACE(int n) /* 检查当前列能否放置皇后 */
{
int i;
for(i = 0; i < n; i++) /* 检查横排和对角线上是否可以放置皇后 */
{
if(queen[i] == queen[n] || abs(queen[i] - queen[n]) == (n - i))
{
return 1;
}
}
return 0;
}
void NQUEENS(int n) /* 回溯尝试皇后位置,n为横坐标 */
{
int i;
for(i = 0; i < max; i++)
{
queen[n] = i; /* 将皇后摆到当前循环到的位置 */
if(!PLACE(n))
{
if(n == max - 1)
{
show(); /* 如果全部摆好,则输出所有皇后的坐标 */
}
else
{
NQUEENS(n + 1); /* 否则继续摆放下一个皇后 */
}
}
}
}
int main()
{
NQUEENS(0); /* 从横坐标为0开始依次尝试 */
printf("%d", sum);
system("pause");
return 0;
}
- Algorlthm gosslp:八皇后问题浅谈
- 浅谈八皇后问题
- 浅谈八皇后问题
- 浅谈八皇后问题
- 浅谈八皇后问题
- 八皇后 n皇后 问题
- 八皇后N皇后问题
- 八皇后问题
- 八皇后问题
- 八皇后问题
- 八皇后问题(2)
- 八皇后问题(3)
- 八皇后问题
- 八皇后问题程序
- 八皇后问题
- 八皇后问题
- 八皇后问题
- 八皇后问题
- linux 中解析命令行参数 (getopt_long用法)
- 一句代码解决全选问题
- C语言入门教程 (六) 条件语句
- json简介
- hdu 1020
- Algorlthm gosslp:八皇后问题浅谈
- [转]浅谈C++中内存分配、函数调用和返回值问题
- 1分2分5分的硬币,组成1角,共有多少种组合。
- hdu 1256
- linux 守护进程 daemon
- hdu 2854 Central Meridian Number--数论--暴力--推导
- 优化上传导入名单模块之Oracle的存储过程简记
- 我对DX11的理解和简化框架与快速游戏制作
- CRF++使用小结(转)