zoukankan      html  css  js  c++  java
  • 八皇后问题 回溯法

    题意:

    给定一个n*n的棋盘, 皇后只能攻击他所在那一列, 左对角线, 右对角线, 求一个所有皇后的不能互相攻击的 solution。

    分析:

    可以从第一行开始枚举, 然后标记该列和主副对角线, 注意点(i,j)左对角线可以标记为 i+j, 右对角线是 i +(n-j), 用3个标记数组标记即可, 回溯法指的是先试试取这个点, 然后标记, 递归回来时候不要这个点, 取消标记。

    /*
    回溯法
    每次摆放后 都把剩下的列 左右对角线标记
    然后再摆放空的位置
    如果到最后或者某一行找不到空的位置
    就回溯
    如果找到最后一行有空的摆放位置 就是答案
    */
    #include<bits/stdc++.h>
    using namespace std;
    int vis[3][50] = {0};//vis[0]负责标记这一列 vis[1]负责标记左对角线 vis[2]负责右对角线
    int n;
    int ans[20];
    int ok = 0;
    void dfs(int row)
    {
        if(row > n)//如果能走到这里 就是答案
        {
            ok++;
            if(ok <= 3)
            {
                for(int j = 1; j < row; j++)
                {
                    printf("%d", ans[j] );
                    if(j == row - 1) printf("
    ");
                    else printf(" ");
                }
            }
    
    
        }
        else
        {
            for(int i = 1; i <= n; i++)
            {
                if(!vis[0][i] && !vis[1][i+row] && !vis[2][i+(n-row)]) //如果这个位置没有标记
                {
                    ans[row] = i;//那vis[row+1][i-1]=vis[row+1][i+1]=vis[row][i] = 1;不能放子
                    vis[0][i] = vis[1][i+row] = vis[2][i+(n-row)] = 1;//标记列 左对角线 右对角线;
                    dfs(row+1);
                    vis[0][i] = vis[1][i+row] = vis[2][i+(n-row)] = 0;//回溯的时候归零
                }
            }
        }
    }
    int main()
    {
        while(scanf("%d", &n) !=EOF)
        {
        dfs(1);
        printf("%d
    ", ok);
        ok = 0;
        //printf("
    ");
        }
    }
  • 相关阅读:
    hdu 4033Regular Polygon(二分+余弦定理)
    hdu 4405Aeroplane chess(概率DP)
    hdu 3853LOOPS (概率DP)
    网络编程基础(转)
    网络编程socket基本API详解(转)
    网络编程之socket(转)
    cf(#div1 B. Dreamoon and Sets)(数论)
    cf(#div1 A. Dreamoon and Sums)(数论)
    hdu 1805Expressions(二叉树构造的后缀表达式)
    hdu1710(Binary Tree Traversals)(二叉树遍历)
  • 原文地址:https://www.cnblogs.com/Jadon97/p/7151594.html
Copyright © 2011-2022 走看看