1342-皇后控制问题

描述

 

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

设计一个拉斯维加斯算法,对于给定的自然数n (1£ n £100)计算在

nxn个方格组成的棋盘上最少要放置多少个皇后才能控制棋盘上的所有方格,且放置的皇后互不攻击。

 

输入

 

 

输入的第一行有1个正整数n。

 

输出

 

输出计算出最少皇后数及最佳放置方案,第一行是最少皇后数;接下来的1行是皇后的最佳放置方案。

 

样例输入

8

样例输出

5

0 3 6 0 0 2 5 8

#include <iostream>
//#include <fstream.h>
#include <time.h>
#include <math.h> 
#include <stdlib.h>  
using namespace std;
//ifstream infile("input.txt"); 
//ofstream outfile("output.txt");  
const unsigned long maxshort=65536L;  
const unsigned long multiplier=1194211693L; 
const unsigned long adder=12345L; 
class RandomNumber 
{ 
public: 
    RandomNumber(void){};
    unsigned long randSeed; 
    RandomNumber(unsigned long s) 
    { 
        if(s==0) 
            randSeed=time(0); 
        else 
            randSeed=s;   
    } 
    unsigned long Random(unsigned long n) 
    { 
        randSeed=multiplier*randSeed+adder; 
        return (unsigned short)((randSeed>>16)%n); 
    }  
    double fRandom(void) 
    { 
        return Random(maxshort)/double(maxshort); 
    } 
};
template <class T>  
void Make2DArray(T** &x, int rows, int cols) 
{ 
    x = new T* [rows]; 
    for(int j = 0; j < rows; j++) 
    { 
        x[j] = new T[cols]; 
    } 
}  
template <class T>  
void Delete2DArray(T** &x, int rows) 
{  
    for(int j = 0; j < rows; j++) 
    { 
        delete[] x[j]; 
    }     
    delete[] x; 
    x = NULL; 
} 
class queen
{
    friend bool nqueen(int m);
    
    private:
        queen(void){};
        bool place(int k);
        bool backtrack(int t);
        int queenslv(int stopVegas);
        bool ctrl(int m);    
        int n,*x,*y,*a,**z;//n=?????????x=k???????????????x[k]??????y=???????????????????????????
                           //a=????????????????????????z=??????????????????
        int cmin,c;//cmin=?????????????????????c=????????????
        RandomNumber rnd; 
};
bool queen::place(int k)
{
    if(x[k]>0) 
        for(int j=1;j<k;j++) 
            if((x[j]>0)&&((abs(k-j)==abs(x[j]-x[k]))||x[j]==x[k])) 
                return false; 
        return true; ;
}
bool queen::ctrl(int m)
{
    int i,j,u,v,count=0;
    for(i=1;i<=m;i++)
        for(j=1;j<=m;j++)
            z[i][j]=0;
    for(i=1;i<=m;i++)
    {
        if(x[i]>0)
        {
            for(j=1;j<=m;j++) {z[i][j]=1;z[j][x[i]]=1;}
            for(u=i,v=x[i];u>=1&&v>=1;u--,v--) z[u][v]=1;
            for(u=i,v=x[i];u<=m&&v>=1;u++,v--) z[u][v]=1;
            for(u=i,v=x[i];u>=1&&v<=m;u--,v++) z[u][v]=1;
            for(u=i,v=x[i];u<=m&&v<=m;u++,v++) z[u][v]=1;
        }
    }
    for(i=1;i<=m;i++)
        for(j=1;j<=m;j++)
            count+=z[i][j];//?????????????????????
    return (count==m*m);
}
int queen::queenslv(int stopVegas) //????????????n?????????
{
    int k=1;
    int count;
    c=0;
    while(k<=stopVegas)
    {
        count=0;
        y[count++]=0;
        for(int i=1;i<=n;i++)
        {
            x[k]=i;
            if(place(k)) y[count++]=i;
        }
        if((x[k++]=y[rnd.Random(count)])>0) c++; 
    }
    return c;
}
bool queen::backtrack(int t)
{
    if(t>n)
    {
        if(ctrl(n)&&(c<=cmin))
        {
            a[0]=c;
            for(int i=1;i<=n;i++)
                a[i]=x[i];
            return true;
        }
        else return false;
    }
    else
    {
        for(int i=0;i<=n;i++)
        {
            x[t]=i;
            if(i>0) c++;
            if((c<=cmin)&&place(t)&&backtrack(t+1))
                return true;
            if(i>0) c--;
        }
        return false;
    }
}
bool nqueen(int n)
{
    queen X;
    X.n=n;
    int *p=new int [n+1];
    int *q=new int [n+1];
    int *ans=new int [n+1];
    int **r;
    Make2DArray(r,n+1,n+1);        
    for(int i=0;i<n;i++) p[i]=0;    
    X.x=p;
    X.y=q;
    X.z=r;
    X.a=ans;
    X.cmin=n;    
    int stop=3;
    int num=0,stopnum=100;
    if(stop>15) stop=n-15;
    //if(stop>12) stopnum=2;
    while(true)
    {
        while(X.queenslv(stop)==0);
        if(X.backtrack(stop+1))
        {
            num++;
            if(X.c<X.cmin)//??????
            {
                X.cmin=X.c;
                num=0;
            }
        }
        if(num>stopnum)
        {
            cout<<ans[0]<<endl;
            for(int i=1;i<n;i++)
                cout<<ans[i]<<" ";
            cout<<ans[n]<<endl;
            return true;
        }
    }
    delete []p;
    delete []q;
    delete []ans;
    Delete2DArray(r,n+1);
    return true;
}
int main()
{
    int n;
    cin>>n;
    return nqueen(n);
    return 0;
}

  

转载于:https://www.cnblogs.com/Rosanna/p/3437049.html

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值