问题描述

在一个nxn个方格组成的棋盘上的任一方格中放置一个皇后,该皇后可以控制他所在 的行,列以及对角线上的所有方格。对于给定的自然数n,在nxn个方格组成的棋盘上最少要放置多少个皇后才能控制棋盘上的所有方格,且放置的皇后互不攻击?
设计一个拉斯维加斯算法,对于给定的自然数n计算在nxn个方格组成的棋盘上最少要放置多少个皇后才能控制棋盘上的所有方格,且放置的皇后互不攻击。

思路解析

所谓拉斯维加斯算法即为随机化算法,但是为了保证结果的切实可行,约束随机数必须满足皇后互不攻击的条件,因为并不是每一行都必须有一个皇后,所以随机数可以为0,在整个棋盘随机化结束后判定是否全部控制棋盘,若true,则比对最小值更新答案,否则不更新。因为随即化算法的正确率并不高,所以设定其随机计算10000次,以期找到最小数量的皇后的解。

Code

#include<bits/stdc++.h>
using namespace std;
#define N 100
#define M 50
int n;
int min_ans=0x3f3f3f, ans[N]; 
bool judge_crl(int row[N], int col[N], int rl[N], int lr[N]){//判断皇后是否完全控制棋盘
    for(int x=1;x<=n;x++){
        for(int y=1;y<=n;y++){
            if(row[x]||col[y]||rl[x+y]||lr[M+x-y]){
                continue;
            }else{
                return false;
            }
        }
    }
    return true;
}
int main()
{
    srand(0);
    cin>>n;
    for(int i=0;i<10000;i++){//计算次数
        int num=0;
        int row[N]={0}, col[N]={0}, rl[N]={0}, lr[N]={0}, vis[N]={0};
        for(int x=1;x<=n;x++){//每行的方案
            while(true){
                int y=rand()%(n+1);//[0, n]
                if(!y){
                    vis[x]=0;
                    break;
                }
                if(!col[y]&&!rl[x+y]&&!lr[M+x-y])//该点可行
                {
                    num++;
                    vis[x]=y;
                    row[x]=1;
                    col[y]=1;
                    rl[x+y]=1;
                    lr[M+x-y]=1;
                    break;
                }
            }
        }
        if(judge_crl(row, col, rl, lr)&&num<min_ans){//更新方案
            min_ans=num;
            for(int i=1;i<=n;i++){
                ans[i]=vis[i];
            }
        }
    }
    cout<<min_ans<<endl;
    for(int i=1;i<=n;i++)
        cout<<ans[i]<<" ";
    getchar();
    getchar();
    return 0;
}