八女王问题如何解?

娇娇 2008-03-29 07:22:29
如何解?(用C++的哦)。谢谢大家的帮助啊。

题目:

编写一个程序解八皇后问题。八皇后问题是:设法在国际象棋的棋盘上放置八个皇后,使得其中任何一个皇后所处的“行”、“列”以及“对角线”上都不能有其它的皇后。
...全文
150 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
popyy0101 2008-04-01
  • 打赏
  • 举报
回复
具体代码不写了,用递归和栈都可以实现,如果不会可以去网上找,有很多
其实说白了就是挨个试,然后回溯……
Mnky 2008-03-31
  • 打赏
  • 举报
回复
第二个的第二部分:

/* Print the results at the end of the run */
void printResults(time_t* pt1, time_t* pt2)
{
double secs;
int hours , mins, intsecs;

printf("End: \t%s", ctime(pt2));
secs = difftime(*pt2, *pt1);
intsecs = (int)secs;
printf("Calculations took %d second%s.\n", intsecs, (intsecs == 1 ? "" : "s"));

/* Print hours, minutes, seconds */
hours = intsecs/3600;
intsecs -= hours * 3600;
mins = intsecs/60;
intsecs -= mins * 60;
if (hours > 0 || mins > 0)
{
printf("Equals ");
if (hours > 0)
{
printf("%d hour%s, ", hours, (hours == 1) ? "" : "s");
}
if (mins > 0)
{
printf("%d minute%s and ", mins, (mins == 1) ? "" : "s");
}
printf("%d second%s.\n", intsecs, (intsecs == 1 ? "" : "s"));

}
}

/* main routine for N Queens program.*/
int main(int argc, char** argv)
{
time_t t1, t2;
int boardsize;

if (argc != 2) {
printf("N Queens program by Jeff Somers.\n");
printf("\tallagash98@yahoo.com or jsomers@alumni.williams.edu\n");
printf("This program calculates the total number of solutions to the N Queens problem.\n");
printf("Usage: nq <width of board>\n"); /* user must pass in size of board */
return 0;
}

boardsize = atoi(argv[1]);

/* check size of board is within correct range */
if (MIN_BOARDSIZE > boardsize || MAX_BOARDSIZE < boardsize)
{
printf("Width of board must be between %d and %d, inclusive.\n",
MIN_BOARDSIZE, MAX_BOARDSIZE );
return 0;
}

time(&t1);
printf("N Queens program by Jeff Somers.\n");
printf("\tallagash98@yahoo.com or jsomers@alumni.williams.edu\n");
printf("Start: \t %s", ctime(&t1));

Nqueen(boardsize); /* find solutions */
time(&t2);

printResults(&t1, &t2);

if (g_numsolutions != 0)
{
#ifdef WIN32
printf("For board size %d, %I64d solution%s found.\n", boardsize, g_numsolutions, (g_numsolutions == 1 ? "" : "s"));
#else
printf("For board size %d, %d solution%s found.\n", boardsize, g_numsolutions, (g_numsolutions == 1 ? "" : "s"));
#endif
}
else
{
printf("No solutions found.\n");
}

return 0;
}
Mnky 2008-03-31
  • 打赏
  • 举报
回复
第二个的第一部分:


#include <stdio.h>
#include <stdlib.h>
#include <time.h>


#ifdef WIN32

#define MAX_BOARDSIZE 21
typedef unsigned __int64 SOLUTIONTYPE;

#else

#define MAX_BOARDSIZE 18
typedef unsigned long SOLUTIONTYPE;

#endif

#define MIN_BOARDSIZE 2

SOLUTIONTYPE g_numsolutions = 0;


/* Print a chess table with queens positioned for a solution */
/* This is not a critical path function & I didn't try to optimize it. */
void printtable(int boardsize, int* aQueenBitRes, SOLUTIONTYPE numSolution)
{
int i, j, k, row;

/* We only calculated half the solutions, because we can derive
the other half by reflecting the solution across the "Y axis". */
for (k = 0; k < 2; ++k)
{
#ifdef WIN32
printf("*** Solution #: %I64d ***\n", 2 * numSolution + k - 1);
#else
printf("*** Solution #: %d ***\n", 2 * numSolution + k - 1);
#endif
for ( i = 0; i < boardsize; i++)
{
unsigned int bitf;
/*
Get the column that was set (i.e. find the
first, least significant, bit set).
If aQueenBitRes[i] = 011010b, then
bitf = 000010b
*/
bitf = aQueenBitRes[i];

row = bitf ^ (bitf & (bitf - 1)); /* get least significant bit */
for ( j = 0; j < boardsize; j++)
{
/* keep shifting row over to the right until we find the one '1' in
the binary representation. There will only be one '1'. */
if (0 == k && ((row >> j) & 1))
{
printf("Q ");
}
else if (1 == k && (row & (1 << (boardsize - j - 1)))) /* this is the board reflected across the "Y axis" */
{
printf("Q ");
}
else
{
printf(". ");
}
}
printf("\n");
}
printf("\n");
}
}


void Nqueen(int board_size)
{
int aQueenBitRes[MAX_BOARDSIZE]; /* results */
int aQueenBitCol[MAX_BOARDSIZE]; /* marks colummns which already have queens */
int aQueenBitPosDiag[MAX_BOARDSIZE]; /* marks "positive diagonals" which already have queens */
int aQueenBitNegDiag[MAX_BOARDSIZE]; /* marks "negative diagonals" which already have queens */
int aStack[MAX_BOARDSIZE + 2]; /* we use a stack instead of recursion */
register int* pnStack;


register int numrows = 0; /* numrows redundant - could use stack */
register unsigned int lsb; /* least significant bit */
register unsigned int bitfield; /* bits which are set mark possible positions for a queen */
int i;
int odd = board_size & 1; /* 0 if board_size even, 1 if odd */
int board_minus = board_size - 1; /* board size - 1 */
int mask = (1 << board_size) - 1; /* if board size is N, mask consists of N 1's */


/* Initialize stack */
aStack[0] = -1; /* set sentinel -- signifies end of stack */

/* NOTE: (board_size & 1) is true iff board_size is odd */
/* We need to loop through 2x if board_size is odd */
for (i = 0; i < (1 + odd); ++i)
{
/* We don't have to optimize this part; it ain't the
critical loop */
bitfield = 0;
if (0 == i)
{
/* Handle half of the board, except the middle
column. So if the board is 5 x 5, the first
row will be: 00011, since we're not worrying
about placing a queen in the center column (yet).
*/
int half = board_size>>1; /* divide by two */
/* fill in rightmost 1's in bitfield for half of board_size
If board_size is 7, half of that is 3 (we're discarding the remainder)
and bitfield will be set to 111 in binary. */
bitfield = (1 << half) - 1;
pnStack = aStack + 1; /* stack pointer */

aQueenBitRes[0] = 0;
aQueenBitCol[0] = aQueenBitPosDiag[0] = aQueenBitNegDiag[0] = 0;
}
else
{
/* Handle the middle column (of a odd-sized board).
Set middle column bit to 1, then set
half of next row.
So we're processing first row (one element) & half of next.
So if the board is 5 x 5, the first row will be: 00100, and
the next row will be 00011.
*/
bitfield = 1 << (board_size >> 1);
numrows = 1; /* prob. already 0 */

/* The first row just has one queen (in the middle column).*/
aQueenBitRes[0] = bitfield;
aQueenBitCol[0] = aQueenBitPosDiag[0] = aQueenBitNegDiag[0] = 0;
aQueenBitCol[1] = bitfield;

/* Now do the next row. Only set bits in half of it, because we'll
flip the results over the "Y-axis". */
aQueenBitNegDiag[1] = (bitfield >> 1);
aQueenBitPosDiag[1] = (bitfield << 1);
pnStack = aStack + 1; /* stack pointer */
*pnStack++ = 0; /* we're done w/ this row -- only 1 element & we've done it */
bitfield = (bitfield - 1) >> 1; /* bitfield -1 is all 1's to the left of the single 1 */
}

/* this is the critical loop */
for (;;)
{
/* could use
lsb = bitfield ^ (bitfield & (bitfield -1));
to get first (least sig) "1" bit, but that's slower. */
lsb = -((signed)bitfield) & bitfield; /* this assumes a 2's complement architecture */
if (0 == bitfield)
{
bitfield = *--pnStack; /* get prev. bitfield from stack */
if (pnStack == aStack) { /* if sentinel hit.... */
break ;
}
--numrows;
continue;
}
bitfield &= ~lsb; /* toggle off this bit so we don't try it again */

aQueenBitRes[numrows] = lsb; /* save the result */
if (numrows < board_minus) /* we still have more rows to process? */
{
int n = numrows++;
aQueenBitCol[numrows] = aQueenBitCol[n] | lsb;
aQueenBitNegDiag[numrows] = (aQueenBitNegDiag[n] | lsb) >> 1;
aQueenBitPosDiag[numrows] = (aQueenBitPosDiag[n] | lsb) << 1;
*pnStack++ = bitfield;
/* We can't consider positions for the queen which are in the same
column, same positive diagonal, or same negative diagonal as another
queen already on the board. */
bitfield = mask & ~(aQueenBitCol[numrows] | aQueenBitNegDiag[numrows] | aQueenBitPosDiag[numrows]);
continue;
}
else
{
/* We have no more rows to process; we found a solution. */
/* Comment out the call to printtable in order to print the solutions as board position*/
/* printtable(board_size, aQueenBitRes, g_numsolutions + 1); */
++g_numsolutions;
bitfield = *--pnStack;
--numrows;
continue;
}
}
}

/* multiply solutions by two, to count mirror images */
g_numsolutions *= 2;
}


Mnky 2008-03-31
  • 打赏
  • 举报
回复
给你两个很牛的例程:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

long sum = 0, upperlim = 1;

void test(long row, long ld, long rd)
{

if (row != upperlim)
{
long pos = upperlim & ~(row | ld | rd);
while (pos)
{
long p = pos & -pos;

pos -= p;
test(row + p, (ld + p) << 1, (rd + p) >> 1);
}
} else
sum++;
}

int main(int argc, char *argv[])
{
time_t tm;
int n = 16;

if (argc != 1)
n = atoi(argv[1]);
tm = time(0);
if ((n < 1) || (n > 32))
{
printf(" 只能计算1-32之间\n");
exit(-1);
}
printf("%d 皇后\n", n);
upperlim = (upperlim << n) - 1;

test(0, 0, 0);
printf("共有%ld种排列, 计算时间%d秒 \n", sum, (int) (time(0) - tm));
}
ayanamiliu 2008-03-31
  • 打赏
  • 举报
回复
4楼是用visual studio 2008 写的吧,这个要包含一些预编译文件,不然不能运行,最起码要
#defint _tmain wmi
mengjunyi 2008-03-29
  • 打赏
  • 举报
回复
连代码都baidu得到.....
-________-b
i_coding 2008-03-29
  • 打赏
  • 举报
回复
自己写的八皇后

#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>

void input(char chess[][8], int n, FILE *);
int Trial(int i, FILE *);
int judge(int *pj, int i, int j);

int row_number[8];//此数组用来存放数组下标对应行放置的棋子所在的列号
//(如row_number[0]就是存放的0行所放棋子的列号)
int cout = 0;//此全局变量cout用来统计一共有多少种符合要求的情况
char chessboard[8][8] = {'o','o','o','o','o','o','o','o',
'o','o','o','o','o','o','o','o',
'o','o','o','o','o','o','o','o',
'o','o','o','o','o','o','o','o',
'o','o','o','o','o','o','o','o',
'o','o','o','o','o','o','o','o',
'o','o','o','o','o','o','o','o',
'o','o','o','o','o','o','o','o'};

int _tmain(int argc, _TCHAR* argv[])
{
FILE *fp = NULL;
if((fp = fopen("八皇后问题.txt", "w")) == NULL)
{
perror("八皇后问题");
exit(0);
}
int total = Trial(0, fp);
fprintf(fp, "\n八皇后问题共有%d种符合要求的情况\n", total);
printf("八皇后问题的%d种符合条件的情况均写入到文件中\n", total);
return 0;
}

int Trial(int i, FILE *fp_trial)
{
if(i > 7)
{
input(chessboard, 8, fp_trial);
fputc('\n', fp_trial);
cout++;
}
else
for(int j = 0; j < 8; ++j)
{
chessboard[i][j] = '*';//在第i行第j列处放置一颗棋子
if(judge(row_number, i, j))
{//合法则放下一个棋子并且将此列序号存入数组cj中
row_number[i] = j;//第i行第j列处放置的棋子合法则将该棋子所在列号j值存放进数组中
Trial(i + 1,fp_trial);
}
chessboard[i][j] = 'o';//清除第i行第j列处的棋子
}
return cout;
}

int judge(int *prow, int i, int j)
{//判断当前放置的棋子是否合法(不合法返回0合法返回1)
for(int n = 0; n < i; n++)
{//将当前行放置棋子的位置与前每一行放置棋子的位置进行比较
//比较方法是首先看它们是否在同一列,不在则看它们是否在一条主对角线上,
//还不在则看它们是否在一条副对角线上。
int *p = prow;
p += n;
if((*p == j) || ((j - i) == (*p - n)) || ((j + i) == (*p + n)))
return 0;
}
return 1;

}

void input(char chess[][8], int n, FILE *fp_input)
{//打印出棋盘状态
for(int i = 0; i < 8; i++)
{
for(int j = 0; j < n; j++)
fprintf(fp_input, "%c ", chess[i][j]);
fputc('\n', fp_input);
}
}

ding1188 2008-03-29
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 abupie 的回复:]
baidu好。
[/Quote]
abupie 2008-03-29
  • 打赏
  • 举报
回复
baidu好。
hastings 2008-03-29
  • 打赏
  • 举报
回复
LZ偷懒,我也偷懒,哈,哈,百度的(不知正确否):
#include   "stdafx.h"   
#include "iostream.h"
#include "string.h"

#define COL 8

void SetQueen(int low, int n);
void OutputResult(void);
int IsCorrect(int col, int row);

char Status[COL + 1][COL + 1];
int AnsID = 0;

int main(int argc, char* argv[])
{
memset(Status, 0, sizeof(Status));
AnsID = 0;
SetQueen(1, COL);

return 0;
}

void SetQueen(int low, int n)
{
int j;

if (low > n)
{
OutputResult();
}
else
{
for (j = 1; j <= n; j++)
{
Status[low][j] = 1;
if (IsCorrect(low, j))
{
SetQueen(low + 1, n);
}
Status[low][j] = 0;
}
}
}

void OutputResult(void)
{
int i, j;

AnsID++;
cout << "\n";
cout << "The " << AnsID << " Answer:" << "\n\n";

for (i = 1; i < COL + 1; i++)
{
for (j = 1; j < COL + 1; j++)
{
if (Status[i][j])
{
cout << "O " ;
}
else
{
cout << "X ";
}
}
cout << "\n";
}
}

int IsCorrect(int col, int row)
{
int i, j;

for (i = 1; i < COL + 1; i++)
{
if ((Status[col][i] == 1) && (i != row))
{
return 0;
}
}

for (i = 1; i < COL + 1; i++)
{
if ((Status[i][row] == 1) && (i != col))
{
return 0;
}
}

for (i = col + 1, j = row + 1; (i < COL + 1 && j < COL + 1); i++, j++)
{
if (Status[i][j] == 1)
{
return 0;
}
}

for (i = col -1, j = row - 1; (i >= 1 && j >= 1); i--, j--)
{
if (Status[i][j] == 1)
{
return 0;
}
}

for (i = col + 1, j = row - 1; (i < COL + 1 && j >= 1); i++, j--)
{
if (Status[i][j] == 1)
{
return 0;
}
}

for (i = col -1, j = row + 1; (i >= 1 && j <= COL + 1); i--, j++)
{
if (Status[i][j] == 1)
{
return 0;
}
}

return 1;

}

64,651

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧