N皇后问题解法

来源:互联网 发布:双色球算法必中1蓝球 编辑:程序博客网 时间:2024/05/07 22:49

这里实现的是经典回溯方法,vector数组中第i个数字X表示第i列选择X行作为i个皇后的位置。

vec[i]==vec[pos]||abs(vec[i] - vec[pos]) == abs(i - pos)主要用来判断vec数组中第pos个位置是否合法,第X和第Y个皇后位置不合法的情况下这2个二货必然在一个对角线上,垂直和水平间距相等与她们连线构成等腰直角三角形。下面是N皇后解法C++代码:

#include <iostream>#include <vector>using namespace std;void printVec(vector<int> vec){for (int i = 0; i<vec.size(); ++i){cout << vec[i] << " ";}cout << endl;}bool isValid(vector<int>& vec, int pos){if (!pos) return true;for (int i = 0; i<pos; i++){if (vec[i]==vec[pos]||abs(vec[i] - vec[pos]) == abs(i - pos)) return false;}return true;}void rec(vector<int>& vec, int pos, int &ret){if (pos >= vec.size()){++ret;printVec(vec);return;}for (int i = 0; i < vec.size(); i++){vec[pos] = i;if (isValid(vec, pos)){rec(vec,pos+1,ret);}}}void eight_queen(int n){vector<int> vec(n);int ret = 0;rec(vec, 0, ret);cout << "total num:" << ret << endl;}int main(int argc, char*argv[]){for (int i = 1; i < 10; i++){cout << i << "皇后解法" << endl;eight_queen(i);}int a = 0;cin >> a;return 0;}


听说8皇后可以10行代码写出来,代码之路果然路漫漫其修远兮,吾将继续敲代码,学算法~~

以下贴一些知乎上牛人的算法作为参考。

这个包含了递归和非递归2种方法。


其他10行版本的牛人算法:

#include <iostream>#include <algorithm>#include <bitset>#include <numeric>#include <utility>int main() {  for (int queens[] = {0,1,2,3,4,5,6,7}; ::std::next_permutation(queens,queens+8); )    if ((::std::bitset<15>(::std::accumulate(queens,queens+8, ::std::make_pair(0, 0), [](::std::pair<int, int> a, int b){return ::std::make_pair((1<<(b+a.second))|a.first,a.second+1);}).first).count() == 8) && (::std::bitset<15>(::std::accumulate(queens, queens+8, ::std::make_pair(0, 0), [](::std::pair<int, int> a, int b){return ::std::make_pair((1<<(7+b-a.second))|a.first, a.second+1);}).first).count() == 8))      ::std::cout << queens[0] << queens[1] << queens[2] << queens[3] << queens[4] << queens[5] << queens[6] << queens[7] << ::std::endl;}


#include <iostream>int sum,ans[8];int solve(int n, long long mark, int *ans){for (int i=n>8?++sum&0:0; n>8&&i<8; i!=7?std::cout << ans[i++] << " " : std::cout << ans[i++] << std::endl);for (int i=0; i<8; !(mark>>i&1)&&!(mark>>(n+i+7)&1)&&!(mark>>(n-i+30)&1)?solve(n+(ans[n-1]=i+1)-i, mark|1ll<<i|1ll<<(n+i+7)|1ll<<(n-i+30), ans):0,i++);return sum;}int main(){std::cout << solve(1, 0, ans) << std::endl;}

#include <cstdio>int queen(int l, int r, int m, int k){    int ans = 0;    for (int i = (~(l | r | m)) & 0xff; i; i -= i & -i)        ans += queen((l | (i & -i)) << 1, (r | (i & -i)) >> 1 , m | (i & -i), k + 1);    return k == 8 ? 1 : ans;}int main(){    printf("%d\n", queen(0, 0, 0, 0));}

int queens (){    int pos[] = {0,1,2,3,4,5,6,7},ans = 0;    while(next_permutation(pos,pos+8)){        bool ok = true;        for(int* p = pos;p<pos+8;p++)            if ( count_if(pos,p,[=](int& j){return p - &j == *p-j || p - &j == j - *p ;}) )                ok = false;        ans += ok;    }    return ans;}

八皇后?十行连 N 皇后都写出来了。int totalNQueens(int n) {    int upperlim = (1 << n) - 1, sum = 0;    std::function<void(int, int, int)> dfs = [&](int row, int l, int r) {        if (row == upperlim) { ++sum; return; }        for (int cur = upperlim & (~(row|l|r)), pos = 0; cur; dfs(row+pos, (l+pos)<<1, (r+pos)>>1)) {            pos = cur & (-cur);            cur -= pos;        }    };    dfs(0, 0, 0);    return sum;}
#include <cstdio>int dfs(int r, int p1, int p2) {int ret = 0, pos = ((1<<8)-1) & ~(r|p1|p2);for (int k = pos & (-pos); pos; pos -= k, k = pos & (-pos))ret += dfs(r+k, (p1+k)<<1, (p2+k)>>1);return r+1 == (1<<8) ? 1 : ret;}int main() {printf("%d\n", dfs(0,0,0));}

int queen(int points[], int size, int deep, int* success, bool check){for (int i = 0; (deep < size || (*success)++ < 0) && i < size && (points[deep] = i + deep * 8) >= 0 && (check = true); i++)for (int before = 0; before < deep || (check && queen(points, size, deep + 1, success, false) < 0); before++) if (points[deep] % 8 == points[before] % 8 || points[deep] == points[before] + (deep - before) * 9 || points[deep] == points[before] + (deep - before) * 7) check = false;return *success;}

#include <stdio.h>#define LOWBIT(x) x&(-x)int solve(int c, int lc, int rc, int sum) {    if(c == 0xFF) return sum + 1;    for (int pos = ((c | lc | rc)&0xFF)^0xFF; pos; pos&=(~(LOWBIT(pos)))) {        sum = solve(c|LOWBIT(pos), (lc|LOWBIT(pos))<<1, (rc|LOWBIT(pos))>>1, sum);    }    return sum;}int main() { printf("%d\n", solve(0, 0, 0, 0)); }

#include <iostream>int dfs(int k=0,int n=8,int c=0,int l=0,int r=0){int i,mask,t,cnt=0;if(k==n) return 1;mask = c | l | r;for(i=0;i<n;i++){t = 1<<i;if(~mask&t)cnt+=dfs(k+1,n,c|t,(l|t)<<1,(r|t)>>1);}return cnt;}int main(){std::cout << dfs() << std::endl;return 0;}

int eight_queen(int level, int y[8], int s[15], int t[15], int r[8]) {if (level == 8)return 1;for (int i = 0; i < 8; ++i)if (y[i] == 0 && s[level - i + 7] == 0 && t[level + i] == 0 && (y[i] = s[level - i + 7] = t[level + i] = 1) && ((r[level] = i) || 1) && (eight_queen(level + 1, y, s, t, r)) && (y[i] = s[level - i + 7] = t[level + i] = 0));return 1;}int main() {int y[8] = {0}, s[15] = {0}, t[15] = {0}, r[8] = {0};eight_queen(0, y, s, t, r);return 0;}

void DFS(unsigned row, unsigned ld, unsigned rd) {    if (row != upperlim) {        unsigned pos = upperlim & ~(row | ld | rd), p;        while (pos) {            p = pos & -pos;            pos -= p;            DFS(row | p, (ld | p) << 1, (rd | p) >> 1);        }    } else ans += 1;}

最后再来个时间空间复杂度都为1的超级算法:
实在醉的不行....
附上知乎关于10行八皇后的连接:
http://www.zhihu.com/question/28543312

0 0
原创粉丝点击