N皇后问题的一种方案
来源:互联网 发布:mac 10.8.2能玩魔兽 编辑:程序博客网 时间:2024/04/29 00:22
一直知道有个N皇后问题(皇后是国际象棋里棋子),不过一看见国际象棋这四个字,就觉得这个问题比较麻烦,所以以前也从来没看过N皇后问题是什么。昨天有精神看了一下该问题,题目也十分简单,突然觉得很有意思,遂把它解了出来。以下是自己的思路和代码:
N皇后描述:
N皇后问题就是说在一个N*N得方格矩阵中,新的皇后必须放入一个它不会被吃掉的方格内,(所谓吃就是国际象棋中皇后的规则,可以在一条直线内随便移动,包括行,列,斜线)所以从第一个皇后放入开始,它都要标记那些地方时不能放置元素的。
N皇后问题以能够放置N个皇后而结束,(即每列一个皇后),每放入一个皇后,都要将其压栈,如果第col列没有合适位置供新的皇后放入(即该列已经从第一个元素遍历到最后一个元素,仍未找到合适位置),则应该将栈顶皇后弹出(eg:皇后的行为i,列为j),从j列i+1行从继续进行下一次探索。
要列出所有的N皇后的答案,则需使用递归。
N皇后思路:
首先定义吃的规则,即皇后放入之后都要定义那些位置是不能放置的。我的想法是做标记,一旦该皇后要从栈顶弹出,则还要相应的撤销标记。标记可以考虑使用C的位运算,(我个人是比较喜欢位运算的)所有空格初始为0,每插入一个皇后,都要在其势力范围内置标记位,比如:插入第一个元素,则让其势力范围内的所有空格|1,插入第2个元素,让其势力范围内所有空格|(1<<1),如果是N皇后,让其势力范围所有空格|(1<<N-1),当改皇后从栈顶弹出式,要撤销标记位,此时让其势力范围内所有空格进行相应的补码计算即可
当然吃的规则可以根据个人习惯有不同的定义,我也是突发奇想,觉得这样做比较有趣,也比较直观。
N皇后算法:
1、检查是否有空余的列。没有,转3。有则检查该列是否有空格能放入。能放入,转2。不能,转4
2、设置相应空格位置状态,将皇后压栈。转1
3、每一列都有一个皇后,则说明成功
4、当前列找不到合适位置放置一个新的皇后,则弹出栈顶皇后,并将其所对应的空格标记取消,回到上一列的下一个位置重新开始1
代码如下:
-------------------------------------------------------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 32
#define BITS 32
int m[MAXSIZE][MAXSIZE];
typedef struct blank
{
int col;
int row;
}Blank;
typedef struct stack
{
Blank elem[MAXSIZE];
int top;
}Stack;
InitStack(Stack **s)
{
*s = (Stack *)malloc(sizeof(struct stack));
(*s)->top = 0;
}
int StackEmpty(Stack *s)
{
return s->top == 0;
}
int Push(Stack *S, Blank *B)
{
if(S->top >= MAXSIZE)
return -1;
else
{
S->elem[S->top] = *B;
S->top++;
}
return 0;
}
int Pop(Stack *S,Blank *B)
{
if(S->top == 0)
return -1;
else
*B = S->elem[--S->top];
return 0;
}
/*将置标志位写为Light(亮灯),应该更有趣吧*/
void Light(int n,int x,int y)
{
int i,j;
int t = 1<<y;
i = x;j = y;
while(i <n && j<n)
{
i++;j++;(m[i][j]) |= t;
}
i = x;j = y;
while(i>0 && j >0)
{
i--;j--;(m[i][j]) |= t;
}
i = x;j = y;
while(i>0 && j<n)
{
i--;j++;(m[i][j]) |= t;
}
i = x;j = y;
while(i<n && j>0)
{
i++;j--;(m[i][j]) |= t;
}
for(j = 0;j<n;j++)
(m[x][j]) |= t;
for(i = 0;i<n;i++)
(m[i][y]) |= t;
}
/*将去标志位改成Darker(变暗)也应该很有趣吧*/
void Darker(int n,int x,int y)
{
int i,j;
int t = (1<<BITS)-1-(1<<y); /*补码*/
i = x;j = y;
while(i <n && j<n)
{
i++;j++;(m[i][j]) &= t;
}
i = x;j = y;
while(i>0 && j >0)
{
i--;j--;(m[i][j]) &= t;
}
i = x;j = y;
while(i>0 && j<n)
{
i--;j++;(m[i][j]) &= t;
}
i = x;j = y;
while(i<n && j>0)
{
i++;j--;(m[i][j]) &= t;
}
for(j = 0;j<n;j++)
(m[x][j]) &= t;
for(i = 0;i<n;i++)
(m[i][y]) &= t;
}
InitBlank(Blank **B)
{
(*B) = (Blank *)malloc(sizeof (struct blank));
(*B)->col = 0;
(*B)->row = 0;
}
DispStack(Stack *s)
{
int i;
Blank *B ;
InitBlank(&B);
for(i = 1; i<=s->top;i++)
{
*B = s->elem[(s->top)-i];
printf("m[%d][%d]/n",B->row,B->col);
}
}
Blank *CB(int col,int row)
{
Blank *B;
B = (Blank *)malloc(sizeof(Blank));
B->col = col;
B->row = row;
return B;
}
/*以下是问题核心*/
void Queen(int n,int r,int c)
{
Stack *s;
Blank *B;
int col,row;
InitStack(&s);
InitBlank(&B);
col = c;
row = r;
while(col < n)
{
while(row < n)
{
if(m[row][col] == 0) /*说明m[col][row]中值未曾改变,可以放置*/
{
Push(s,CB(col,row)); /*把该皇后(i,j)压栈*/
Light(n,row,col);/*修改势力范围,即同行,同列,左斜,右斜都设置标志位*/
col++;
row = 0;
break;
}else
row ++;
}
if(row > n-1 && col < n)
{
if(col == 0)/*已经是第一列,并且是最后一个元素已经尝试,则跳出*/
break;
else
{
Pop(s,B); /*如果列还没遍历到第n个,所有的行已经不能放置,则表示应该回溯*/
Darker(n,B->row,B->col);/*将该皇后弹出后,修改其改变过的标志位*/
col = B->col;
row = B->row+1; /* 返回上一列的下一个位置继续寻找*/
}
}
}
if(col > n-1)//说明已经找到符合条件的一组数据
{
DispStack(s);
printf("/n");
while(!StackEmpty(s))
{
Pop(s,B);
Darker(n,B->row,B->col);
}
col = 0;
row = B->row+1;
Queen(n,row,col);
}
}
int main(void)
{
int col,row;
int n ;
printf("输入数组维数(不能大于32)/n");
scanf("%d",&n);
for(col = 0;col < n;col++)
for(row = 0;row < n; row++)
m[col][row] = 0;
Queen(n,0,0);
return 0;
}
这个解法只是自己的一个思路的实现,远谈不上理想,以后有机会还会补充。
- N皇后问题的一种方案
- N皇后的问题
- N皇后问题 求解方案数
- 八皇后、N皇后问题的求解。
- N皇后问题的实现
- N皇后问题的解决
- 小小的N皇后问题
- n皇后问题的解法
- N*N皇后问题
- 【codevs1295 N皇后问题(不输出方案)】回溯法
- 【codevs1295 N皇后问题(不输出方案)】回溯法
- 八皇后问题的一种解法
- 8皇后问题的一种简单求解
- 八皇后 n皇后 问题
- 八皇后N皇后问题
- 由八皇后问题到n皇后的推广
- 基于八皇后上的N皇后问题
- n皇后方案总数的位运算优化
- 让vdsp与uclinux共舞(2):vdsp的影响
- 浮点前导数字的分布
- 快速立即除法的乘法实现(通用算法)
- fstream处理中文时的小问题
- 为什么说“全局变量”是危险的?该在哪里使用它?
- N皇后问题的一种方案
- PHP解疑
- Microsoft Expression Studio 2 简体中文正式版 序列号
- [转].bash_profile和.bashrc的区别
- photoshop另存为dds文件时的错误
- web打印带分页
- Windows快捷键
- 临终关怀?抑或一切照旧?PR咋又更新了?
- Dreamweaver 不自动生成css,Dreamweaver 不自动生成样式