8皇后

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

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

  • 首先我们真的需要一个矩阵吗?我之所以没做下去就是因为给我一个矩阵我不知道咋用啊!
    其实,我们用矩阵是因为我们要在矩阵里面储存变量的值啊,而这里面,你建立了矩阵后储存什么呢?棋子是否在那个位置用矩阵也太浪费了吧!
    所以简单一点,我们表示棋子在每一行/列的位置就行了,所以一维数组就搞定了。

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

  • 然后,我们发现这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颗棋子,怎么处理呢?两两组合的话情况有很多。。?
--这里的话,可以用两层循环来对所有的两两组合判断

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

  • 首先我们每一列/每一行都需要放置一个棋子
    那先在第一行假设一个位置,这个确定之后就会排除掉剩下的位置,我们第二行也确定一个,假设我们从第一个开始试,用上面的判断条件,如果满足则继续第三层。。。最后如果第8层也满足的话,这就是一种符合的思路
    听起来还可以,我试试

文章参考何海涛大神文章

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,099评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,828评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,540评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,848评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,971评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,132评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,193评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,934评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,376评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,687评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,846评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,537评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,175评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,887评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,134评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,674评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,741评论 2 351

推荐阅读更多精彩内容

  • 前言 八皇后问题是一个古老而著名的问题,是回溯算法的典型例题。该问题是十九世纪著名的数学家高斯1850年提出:在8...
    jacky123阅读 1,540评论 0 3
  • 首先,可归纳问题的条件为,8皇后之间需满足:1.不在同一行上2.不在同一列上3.不在同一斜线上4.不在同一反斜线上...
    yuanxiaolan阅读 502评论 0 1
  • 背景 一年多以前我在知乎上答了有关LeetCode的问题, 分享了一些自己做题目的经验。 张土汪:刷leetcod...
    土汪阅读 12,741评论 0 33
  • 史上最全的iOS面试题及答案 iOS面试小贴士———————————————回答好下面的足够了----------...
    Style_伟阅读 2,346评论 0 35
  • 他们在秋天相遇,在秋天重逢。 遇见他之前,她是一名心理咨询师,主攻犯罪心理。博士毕业前,她申请到监狱当心理咨询顾问...
    谢女遐阅读 426评论 0 3