C算法&面试题程序员我是程序员;您好程先生;叫我序员就好了

8皇后

2016-03-24  本文已影响140人  AwesomeAshe

文章的后面是我最开始的想法,不巧妙,有点过于笨拙了,实现起来不好弄。
但是里面的一些想法还是不错的。

重新来看这道题,怎样简化一些:

因此,我们定义一个长度为8的数组,每个数组元素的值代表这一行/列棋子的位置,因此值的范围也在0-7

全排列

那么怎么实现求这个排列呢?

void Permutation(char* pStr, char* pBegin)
{
    if (!pStr || !pBegin)
        return;
    
        // if pBegin points to the end of string,
        // this round of permutation is finished,
        // print the permuted string
        if (*pBegin == '\0')
        {
            printf("%s\n", pStr);
            
        }
    // otherwise, permute string
        else
        {
            for (char* pCh = pBegin; *pCh != '\0'; ++pCh)
            {
                // swap pCh and pBegin
                char temp = *pCh;
                *pCh = *pBegin;
                *pBegin = temp;
            
                Permutation(pStr, pBegin + 1);
                
                // restore pCh and pBegin
                temp = *pCh;
                *pCh = *pBegin;
                *pBegin = temp;
            }
        }
}

具体的这个函数先不介绍,下次单独说

step2 实现

#include <iostream>

int count = 0;//存储当前解的个数

void arr_swap(int*arr,int a, int b)
{
    int tmp = arr[a];
    arr[a] = arr[b];
    arr[b] = tmp;
}

bool queen_conflic(int* arr, int len)
{
    for (int i = 0; i < len; i++)
    {
        for (int j = i + 1; j < len; j++)
        {
            if (arr[i] - arr[j] == j - i || arr[j] - arr[i] == j - i)
                return true;
        }
    }
    return false;
}
void print_arr(int* arr, int len)
{
    std::cout << "solution_" << count<<":" << std::endl;
    for (int i = 0; i < len; i++)
        std::cout << arr[i] << " ";
    std::cout << std::endl;
}

void permutation(int *arr, int len, int index)
{
    if (index == len)
    {
        if (!queen_conflic(arr, len))
        {
            ++count;
            print_arr(arr, len);
        }
    }
    else
    {
        for (int i = index; i < len; i++)
        {
            arr_swap(arr, i, index);
            permutation(arr, len, index + 1);
            arr_swap(arr, index, i);
        }
    }
}


void eightQueen()
{
    const int queens = 8;
    int arr[queens];
    for (int i = 0; i < queens; i++)
    {
        arr[i] = i;//eight different values
    }
    permutation(arr, queens, 0);
}

int main()
{
    eightQueen();
}

结果:

运算结果(部分)

wiki上说有12个独立解。但是总的解数是92个,因为包含了一些旋转的情况。



下面是我几天前尝试着做的时候的想法,显然我原本的想法失败了,因为思路还不是很清晰

额。。这个算法问题应该说很多人都听说过甚至都做过了,但是我直到今天才认真的思考这个问题,原因之一是因为,之前我一直觉得,这个可能很难。。当然现在我才刚刚审题,我决定写一下我的思路。

首先,我想到用一个8x8的矩阵表示坐标,然后假定我们得到了8个坐标
要判断是否会被吃掉,就是判断是否所有的棋子都满足:
1,不在同一条直线上
2,不在同一条斜线上
而直线和斜线都对应着两种情况
我想先写一个判断两个棋子坐标的函数:

struct point
{
    int x;
    int y;
};

//to judge
bool StraightLine(point* p1, point* p2)
{
    return (p1->x == p2->x || p1->y == p2->y);
        
}
bool CrossLine(point* p1, point* p2)
{
    return (abs(p1->x - p2->x) == abs(p1->y - p2->y));
}
bool conflict(point*p1, point*p2)
{
    return (StraightLine(p1, p2) || CrossLine(p1, p2));
}

现在就可以判断两颗棋子是否符合要求了。

但是有8颗棋子,怎么处理呢?两两组合的话情况有很多。。?
--这里的话,可以用两层循环来对所有的两两组合判断

这样貌似有点复杂,走不通,再想想。。

文章参考何海涛大神文章

上一篇 下一篇

猜你喜欢

热点阅读