2n皇后黑皇后和白皇后超详细解析c语言,算法

#include<cstdio>
#include<cmath>
#include<string>
#include<algorithm>
#include<iostream>
using namespace std;
int mp[10][10];
int vx[10], vy[10], vd1[20], vd2[20];//分别表示行与列与左对角线和右对角线
int n,ans;
void dfs(int x,int p)//一个用来表示行x ,一个用来表式放的是黑皇后(1)还是白皇后(2) ,先放黑后放白
{
    if (x == n&&p==2)//到了最后一行且放的是白皇后则结束
    {
        ans++;
        return;
    }
    if (x == n)
    {
        dfs(0, p + 1);//黑皇后放完开始放白皇后,又重新从第0行开始放白皇后
        return;
    }
    for (int i = 1; i <= n; i++)//x代表行i代表列
    {//列如 mp[x][y]==0则表示不可以放置皇后 ,mp[x][y]==1则表示可以放置皇后 ,
        if (mp[x][i] && vy[i] != 3 && vy[i] != p && vd1[x + i] != 3 && vd1[x + i] != p && vd2[x - i + n] != 3 && vd2[x - i + n] != p)
        //x+i左下对角,x-i+n右下对角
        // 注意是对每一行的每一个值减或加比如
        //     1        2          3              4
         // 1  (1+1) (1+2)    (1+3)         (1+4)
        // 2   2+1      2+2        2+3(5)            2+4(6)
        // 3   3+1      3+2(5)        3+3(6)             3+4  
        // 4
        //    1           2                3                    4
        // 1  1-1+4      1-2+4            1-3+4                 1-4+4
        // 2  2-1+4(5)      2-2+4(4)             2-3+4                 2-4+4    
        // 3  3-1+4(6)       3-2+4(5)             3-3+4(4)
        // 4        
            //表示mp[x][i]第x行第i列的位置,存在也就是说可以放皇后,vy[i]!=3(主要针对两次都放置了之后而言)表示列的方向没有放置两个皇后因为1代表黑皇后2代表白皇后 1+2=3表示两个皇后均已经放置,!=p是针对第一次而言第一次p=1 ,第二次p=2 而已经填入的列如vy[i]=1,所以不冲突
        {
            mp[x][i] = 0;//表示改位置放入皇后;
            vy[i] += p;
            vd1[x + i] += p;
            vd2[x - i + n] += p;
            dfs(x + 1, p);
            vy[i] -= p;
            vd1[x + i] -= p;
            vd2[x - i + n] -= p;
            mp[x][i] = 1;//重新清回来表示该位置可以防止皇后为了其他的情况可以正常运行
        }
    }
}
int main()
{
    int n;
    scanf("%d", &n);
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
        {
            scanf("%d", &mp[i][j]);
            //数为1可以放置皇后数为0不可以放置皇后
        }
    }
    dfs(0, 1);
    cout << ans << endl;
    return 0;
}

/*#include<bits/stdc++.h>
using namespace std;
const int s = 100;
int vy[s], vd[s], vv[s];//列左下,右下对角线
int map[s][s];
int n, ans;
void dfs(int x, int p)
{
    if (x == n && p == 2)
    {
        ans++;
        return;
    }
    if (x == n && p == 1)//表示第一种皇后放完的情况 p不加也可以我们直接在最后面判断即可 
    {
        dfs(0, p + 1);
        return;//这里必须有return 因为他不用计算之后回溯继续往下计算,因为一种皇后已经被算完了 
    }
    for (int i = 1; i < n; i++)
        //这里横向来看一共就是实打实的n个格子不可能从零开始因为这样凑不齐对角线,必须到n不然的话第n-1个格子凑不齐 
    {
        //x可以表示行map==1表示可以放置 ,,3表示两次都放过了 
        if (map[x][i] && vy[i] != 3 && vy[i] != p && vd[x + i] != p % %vd[x + i] != 3 && vv[x - i + n] != 3 && vv[x - i + n] != p)
        {
            map[x][i] = 0;//标记为已访问,之后不可以访问
            vy[i] += p;
            vd[x + i] += p;
            vv[x - i + n] += p;
            dfs(x + 1, p);//表示访问下一个
            vy[i] -= p;
            vd[x + i] -= p;
            vv[x - i + n] -= p;//回溯 
            map[i][j] = 1;
        }
    }
}
int main()
{
    cin >> n;

    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
        {
            cin >> map[i][j];
        }
    }
    dfs(0, 1);//从零开始比较好因为这样前面那个就表示已经放好,而1表示等待放入,1表示放入白皇后,2表示放入黑皇后,当一个格子等于三就表示他黑皇后放过,白皇后也放过
    //因为一个格子既可以放黑也可以放白,是一种相对概念当一个格子放了黑那么其他就只能放白,但是第二位同时这个格子也可以放置白,那么相对黑也会产生不同的情况 
    cout << ans;
    return 0;
}*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值