2754 - 八皇后

问题描述:http://poj.grids.cn/practice/2754/

2754 - 八皇后

Time Limit:
1000ms
Memory limit:
65536kB

题目描述
会下国际象棋的人都很清楚:皇后可以在横、竖、斜线上不限步数地吃掉其他棋子。
如何将8个皇后放在棋盘上(有8 * 8个方格),使它们谁也不能被吃掉!这就是著名的八皇后问题。
对于某个满足要求的8皇后的摆放方法,定义一个皇后串a与之对应,即a=b1b2...b8,其中bi为相应摆法中第i行皇后所处的列数。
已经知道8皇后问题一共有92组解(即92个不同的皇后串)。给出一个数b,要求输出第b个串。
串的比较是这样的:皇后串x置于皇后串y之前,当且仅当将x视为整数时比y小。

输入
第1行是测试数据的组数n,后面跟着n行输入。每组测试数据占1行,包括一个正整数b(1 <= b <= 92)

输出
输出有n行,每行输出对应一个输入。输出应是一个正整数,是对应于b的皇后串。
样例输入

2
1
92

样例输出

15863724
84136275 

 

首先是用了迭代法,把八层循环都列了出来。。 循环太多了,各种复制粘贴和查找替换。。最后内存252kb,时间0ms

/********************************************************************************************************
解题思路:

经典方法用的是递归和回溯,穷举所有情况。我用了八层的迭代来试试,主要要找一个高效的,
判定当前棋子是否能够安全放置的方法,并且拿掉此棋子还能够还原它对其他棋子的影响。

按照每行来迭代,自然不考虑行的限制。

用一个标识数组column[8]来判断当前列是否能够放棋子,并且保存受到了几个棋子的影响,
如果受到多个棋子影响了,回溯时拿掉一个棋子,不会影响其他棋子的影响。

用另2个标识数组diagonal_1[15]和diagonal_2[15]来判断当前右斜线和左斜线分别能否放棋子。
对于棋子board[i][j],所在右斜线用diagonal_1[j-i+7]表示,左斜线用diagonal_2[i+j]表示。

内存:252kB
时间:0ms
*******************************************************************************************************
*/

#include 
<iostream>
#include 
<cmath>
#include 
<cctype>
#include 
<string>
#include 
<map>
#include 
<set>
#include 
<vector>
#include 
<algorithm>
#include 
<list>
#include 
<stack>
#include 
<cstring>
//#include <stdlib.h>
//#include <iomanip>

using namespace std;

inline 
void add_chess(unsigned column[], unsigned diagonal_1[], unsigned diagonal_2[], int i, int j)
{
    column[j]
++;
    diagonal_1[j
-i+7]++;
    diagonal_2[i
+j]++;
}

inline 
void cancel_chess(unsigned column[], unsigned diagonal_1[], unsigned diagonal_2[], int i, int j)
{
    column[j]
--;
    diagonal_1[j
-i+7]--;
    diagonal_2[i
+j]--;
}

int main()
{
    
//存放所有结果
    unsigned answers[92][8];
    
//存放一次结果
    unsigned count = 0, hang[8= {0};

    
//用来记录当前的列是否可以放棋子
    unsigned column[8= {0};
    unsigned diagonal_1[
15= {0}, diagonal_2[15= {0};

    
//////////////////////////////////////////////////////////////////////////
    //枚举所有情况,并且剪枝+回溯
    
//第0层循环
    for (hang[0= 0; hang[0< 8; hang[0]++)
    {
        add_chess(column, diagonal_1, diagonal_2, 
0, hang[0]);
        
//第1层循环
        for (hang[1= 0; hang[1< 8; hang[1]++)
        {
            
if (column[hang[1]] == 0 && diagonal_1[hang[1]+6== 0 && diagonal_2[hang[1]+1== 0)
            {
                add_chess(column, diagonal_1, diagonal_2, 
1, hang[1]);
                
//第2层循环
                for (hang[2= 0; hang[2< 8; hang[2]++)
                {
                    
if (column[hang[2]] == 0 && diagonal_1[hang[2]+5== 0 && diagonal_2[hang[2]+2== 0)
                    {
                        add_chess(column, diagonal_1, diagonal_2, 
2, hang[2]);
                        
//第3层循环
                        for (hang[3= 0; hang[3< 8; hang[3]++)
                        {
                            
if (column[hang[3]] == 0 && diagonal_1[hang[3]+4== 0 && diagonal_2[hang[3]+3== 0)
                            {
                                add_chess(column, diagonal_1, diagonal_2, 
3, hang[3]);
                                
//第4层循环
                                for (hang[4= 0; hang[4< 8; hang[4]++)
                                {
                                    
if (column[hang[4]] == 0 && diagonal_1[hang[4]+3== 0 && diagonal_2[hang[4]+4== 0)
                                    {
                                        add_chess(column, diagonal_1, diagonal_2, 
4, hang[4]);
                                        
//第5层循环
                                        for (hang[5= 0; hang[5< 8; hang[5]++)
                                        {
                                            
if (column[hang[5]] == 0 && diagonal_1[hang[5]+2== 0 && diagonal_2[hang[5]+5== 0)
                                            {
                                                add_chess(column, diagonal_1, diagonal_2, 
5, hang[5]);
                                                
//第6层循环
                                                for (hang[6= 0; hang[6< 8; hang[6]++)
                                                {
                                                    
if (column[hang[6]] == 0 && diagonal_1[hang[6]+1== 0 && diagonal_2[hang[6]+6== 0)
                                                    {
                                                        add_chess(column, diagonal_1, diagonal_2, 
6, hang[6]);
                                                        
//第7层循环
                                                        for (hang[7= 0; hang[7< 8; hang[7]++)
                                                        {
                                                            
if (column[hang[7]] == 0 && diagonal_1[hang[7]] == 0 && diagonal_2[hang[7]+7== 0)
                                                            {
                                                                
//添加一组解
                                                                memcpy(answers[count], hang, sizeof(unsigned)*8);
                                                                count
++;
                                                            }
                                                        }
                                                        cancel_chess(column, diagonal_1, diagonal_2, 
6, hang[6]);
                                                    }
                                                }
                                                cancel_chess(column, diagonal_1, diagonal_2, 
5, hang[5]);
                                            }
                                        }
                                        cancel_chess(column, diagonal_1, diagonal_2, 
4, hang[4]);
                                    }
                                }
                                cancel_chess(column, diagonal_1, diagonal_2, 
3, hang[3]);
                            }
                        }
                        cancel_chess(column, diagonal_1, diagonal_2, 
2, hang[2]);
                    }
                }
                cancel_chess(column, diagonal_1, diagonal_2, 
1, hang[1]);
            }
        }
        cancel_chess(column, diagonal_1, diagonal_2, 
0, hang[0]);
    }

    
//////////////////////////////////////////////////////////////////////////
    //输入结果
    int n, tmp;
    cin 
>> n;
    
while (n--)
    {
        cin 
>> tmp;
        
for (int i = 0; i < 8; i++)
            cout 
<< answers[tmp-1][i]+1;
        cout 
<< "\n";
    }

    
return 0;
}

然后用了经典的递归和回溯的方法,深度优先搜索一个八叉树。最后内存256kb,时间0ms

#include <iostream>
#include 
<cmath>
#include 
<cctype>
#include 
<string>
#include 
<map>
#include 
<set>
#include 
<vector>
#include 
<algorithm>
#include 
<list>
#include 
<stack>
#include 
<cstring>
//#include <stdlib.h>
//#include <iomanip>

using namespace std;

//用来记录当前的列是否可以放棋子
unsigned column[8= {0};
unsigned diagonal_1[
15= {0}, diagonal_2[15= {0};

//存放所有结果
unsigned answers[92][8];

//hang存放一次结果,count记录结果个数
unsigned ans_count = 0, hang[8= {0};

inline 
void add_chess(int i, int j)
{
    column[j]
++;
    diagonal_1[j
-i+7]++;
    diagonal_2[i
+j]++;
}

//i, j分别是行和列
inline void cancel_chess(int i, int j)
{
    column[j]
--;
    diagonal_1[j
-i+7]--;
    diagonal_2[i
+j]--;
}

inline 
bool judge(int i, int j)
{
    
if (column[j] == 0 && diagonal_1[j-i+7== 0 && diagonal_2[i+j] == 0)
        
return true;
    
return false;
}

void putQueen(int ith_row)
{
    
//则产生了一组新解,也即树的一条路径
    if (ith_row == 8)
    {
        memcpy(answers[ans_count], hang, 
sizeof(unsigned)*8);
        ans_count
++;
    }
    
//则查找当前行的8个棋盘格,如果可以放棋子,就放一个并且进行记录,标记对其它棋子的影响
    
//并且往下深度递归,递归完,回溯到这一处时,还要取消对其它棋子的影响标记
    for (int j = 0; j < 8; j++)
    {
        
if (judge(ith_row, j))
        {
            hang[ith_row] 
= j;
            add_chess(ith_row, j);
            putQueen(ith_row
+1);
            cancel_chess(ith_row, j);
        }
    }
}

int main()
{
    
//递归所有情况,并且剪枝+回溯
    putQueen(0);

    
//输入结果
    int n, tmp;
    cin 
>> n;
    
while (n--)
    {
        cin 
>> tmp;
        
for (int i = 0; i < 8; i++)
            cout 
<< answers[tmp-1][i]+1;
        cout 
<< "\n";
    }

    
return 0;
}

 

posted @ 2011-09-14 22:09  InfantSorrow  阅读(963)  评论(0编辑  收藏  举报