ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

n皇后问题javascript解法

2021-06-10 16:30:24  阅读:144  来源: 互联网

标签:arr return javascript let 皇后 false true 解法 row


 

function queen(n) {

                if(n < 2) {
                    return;
                }
                let i = 0;
                let arr = [];
                //保存皇后放在那列的索引
                for(let k = 0; k < n; k++) {
                    arr.push(0);
                }
                while(i < n) {

                    let solve = true;
                    //let j = arr[r];
                    for(let j = arr[i]; j < n; j++) {
                        //检查该处皇后是否不被上面行的皇后攻击
                        let a = checkLeftTop(i, j, arr);
                        let b = checkTop(i, j, arr);
                        let c = checkRightTop(i, j, n, arr);

                        solve = a && b && c;
                        if(solve) {
                            //放这行皇后的列位置
                            arr[i] = j;
                            break;
                        }
                    }
                    //此行所有位置都不满足,回溯到祖先行
                    if(solve === false) {
                        let info = back(i, arr, n);
                        if(info.status) {
                            i = info.row;
                            continue;
                        } else {
                            //第一行全都遍历不满足,无解
                            console.log(info);
                            console.error("no solve");
                            break;
                        }
                    }
                    i++;
                }
                //success
                if(i === n) {
                    console.log(arr);
                    return arr;
                }
            }
            /**
             * 不被攻击true
             * @param {number} i row
             * @param {number} j column
             * @param {array} a 
             * @returns boolean
             */
            function checkLeftTop(i, j, a) {
                for(let m = i - 1, n = j - 1; m >= 0 && n >= 0; m--, n--) {
                    //a[m] 上行皇后所在列
                    if(a[m] === n) {
                        return false;
                    }
                }
                return true;
            }

            function checkTop(i, j, a) {
                for(let m = i - 1; m >= 0; m--) {
                    if(a[m] === j) {
                        return false;
                    }
                }
                return true;
            }

            function checkRightTop(i, j, colNum = 8, a) {

                for(let m = i - 1, n = j + 1; m >= 0 && n < colNum; m--, n++) {
                    if(a[m] === n) {
                        return false;
                    }
                }
                return true;
            }

            /**
             * back parent row
             * @param {number} i row
             * @param {array} a 
             * @param {number} rowNum 
             * @returns 
             */
            function back(i, a, rowNum) {

                let status = false;
                //回溯列
                let row = i;
                //console.log(i,a);
                for(let r = i - 1; r >= 0; r--) {
                    if(a[r] < rowNum - 1) {
                        a[r] = a[r] + 1;
                        //回到上一行
                        row = r;
                        status = true;
                        //清空数据
                        for(let m = r + 1; m < rowNum; m++) {
                            a[m] = 0;
                        }
                        break;
                    }
                }
                return {
                    status,
                    row
                }
            }

            queen(8);

 

随机解法,理解回溯算法:

function randomQueen(n) {

                if(n < 2) {
                    return;
                }
                let i = 0;
                //保存每行遍历过的列,回溯时清空
                let caches = [];
                //保存皇后放在那列的索引
                let arr = [];
                for(let k = 0; k < n; k++) {
                    arr.push(0);
                    caches.push([]);
                }
                while(i < n) {

                    let solve = true;
                    let cache = caches[i];
                    //for(let )
                    while(cache.length !== n) {
                        let temp = [];
                        for(let m = 0; m < n; m++) {
                            let index = cache.indexOf(m);
                            if(index === -1) {
                                temp.push(m);
                            }
                        }
                        let l = temp.length;
                        let index = Math.random() * l | 0;
                        let j = temp[index];
                        //检查
                        let a = checkLeftTop(i, j, arr);
                        let b = checkTop(i, j, arr);
                        let c = checkRightTop(i, j, n, arr);

                        solve = a && b && c;
                        cache.push(j);
                        if(solve) {
                            //放这行皇后的列位置
                            arr[i] = j;
                            break;
                        }

                    }

                    if(solve === false) {
                        let info = back(i, n, caches);
                        if(info.status) {
                            i = info.row;
                            continue;
                        } else {
                            //第一行全都遍历不满足,无解
                            console.log(info);
                            console.error("no solve");
                            break;
                        }
                    }

                    i++;
                }

                if(i === n) {
                    console.log(arr,caches);
                    return arr;
                }
            }

            /**
             * 不被攻击true
             * @param {number} i row
             * @param {number} j column
             * @param {array} a 
             * @returns boolean
             */
            function checkLeftTop(i, j, a) {
                for(let m = i - 1, n = j - 1; m >= 0 && n >= 0; m--, n--) {
                    //a[m] 上行皇后所在列
                    if(a[m] === n) {
                        return false;
                    }
                }
                return true;
            }

            function checkTop(i, j, a) {
                for(let m = i - 1; m >= 0; m--) {
                    if(a[m] === j) {
                        return false;
                    }
                }
                return true;
            }

            function checkRightTop(i, j, colNum = 8, a) {

                for(let m = i - 1, n = j + 1; m >= 0 && n < colNum; m--, n++) {
                    if(a[m] === n) {
                        return false;
                    }
                }
                return true;
            }

            function back(i, rowNum, caches) {

                let status = false;
                let row = i;
                let colNum = rowNum;
                for(let r = i - 1; r >= 0; r--) {
                    if(caches[r].length < colNum) {

                        //回到上一行
                        row = r;
                        status = true;
                        //清空数据
                        for(let m = r + 1; m < rowNum; m++) {
                            caches[m] = [];
                        }
                        break;
                    }
                }
                return {
                    status,
                    row
                }
            }
            randomQueen(10);

 

 

 

标签:arr,return,javascript,let,皇后,false,true,解法,row
来源: https://blog.csdn.net/qq_37057443/article/details/117783896

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有