zoukankan      html  css  js  c++  java
  • goj N皇后问题

    Problem Description:

    在N*N的方格棋盘放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的斜线上。
    你的任务是,对于给定的N,求出有多少种合法的放置方法。

    Input:

    共有若干行,每行一个正整数N≤12,表示棋盘和皇后的数量;如果N=0,表示结束。

    Output:

    共有若干行,每行一个正整数,表示对应输入行的皇后的不同放置数量。

    Sample Input:

    1
    8
    5
    0

    Sample Output:

    1
    92
    10
    解题思路:N皇后问题即任两个皇后都不能处于同一条横行、纵行或斜线上。求解这一问题涉及到试探+回溯算法,
    用递归就可以将思路清晰地展现出来。
    我们在试探的过程中,皇后的放置需要检查他的位置是否和已经放置好的皇后发生冲突,
    为此需要以及检查函数place()来检查当前要放置皇后的位置,是不是和其他已经放置的皇后发生冲突。
    假设有两个皇后被放置在(i,j)和(k,l)的位置上,明显,当且仅当|i-k|=|j-l| 时,两个皇后才在同一条对角线上。
    (1)先从首位开始检查,如果不能放置,接着检查该行第二个位置,
    依次检查下去,直到在该行找到一个可以放置一个皇后的地方,然后保存当前状态,转到下一行重复上述方法的检索。 
    (2)如果检查了该行所有的位置均不能放置一个皇后,
    说明上一行皇后放置的位置无法让所有的皇后找到自己合适的位置,因此就要回溯到上一行,重新检查该皇后位置后面的位置。
    AC代码:
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int queen[15],cnt,n;    //存放各皇后所在的列号,cnt为解个数
     4 bool place(int row){     /* 检查横列和对角线上是否可以放置皇后 */
     5     for(int i=0;i<row;++i){ //和已经摆放好的皇后进行比较
     6         if ((queen[i]==queen[row]) || (abs(queen[i]-queen[row])==abs(row-i)))
     7             return false;
     8     }
     9     return true;
    10 }
    11 void QueenSet(int row){/* 回溯尝试皇后位置,row为横坐标 */
    12     for(int col=0;col<n;++col){ //首先将皇后放在第0列的位置,对于第一次来说是肯定成立的
    13         queen[row]=col;/* 将皇后摆到当前循环到的位置 */
    14         if(place(row)){//如果放置成功
    15             if(row==n-1)++cnt;/* 如果全部摆好,则解的个数加1 */
    16             else QueenSet(row+1);/* 否则继续摆放下一个皇后 */
    17         }//这里递归时已经将当前地址压进栈中
    18     }//所以当所在行的所有列不满足时,便会出栈,即回溯,返回到上一行的下一列
    19 }
    20 int main(){
    21     while(cin>>n && n){
    22         cnt=0;//解的个数
    23         QueenSet(0);/* 从横坐标为0开始依次尝试 */
    24         cout<<cnt<<endl;
    25     }
    26     return 0;
    27 }
    而杭电hdu2553这题却需要先打表,不然会超时,题目给出的N最大为10。
    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2553
    AC代码:
    #include<bits/stdc++.h>
    using namespace std;
    int queen[11],num[11],cnt,n,N;    //存放各皇后所在的列号,cnt为解个数,num数组记录每n个皇后的解
    bool place(int row){     /* 检查横列和对角线上是否可以放置皇后 */
        for(int i=0;i<row;++i){ //和已经摆放好的皇后进行比较
            if ((queen[i]==queen[row]) || (abs(queen[i]-queen[row])==abs(row-i)))
                return false;
        }
        return true;
    }
    void QueenSet(int row){/* 回溯尝试皇后位置,row为横坐标 */
        for(int col=0;col<n;++col){ //首先将皇后放在第0列的位置,对于第一次来说是肯定成立的
            queen[row]=col;/* 将皇后摆到当前循环到的位置 */
            if(place(row)){//如果放置成功
                if(row==n-1)++cnt;/* 如果全部摆好,则解的个数加1 */
                else QueenSet(row+1);/* 否则继续摆放下一个皇后 */
            }
        }
    }
    int main(){
        for(n=1;n<11;++n){
            cnt=0;//解的个数
            QueenSet(0);/* 从横坐标为0开始依次尝试 */
            num[n]=cnt;
        }
        while(cin>>N && N)
            cout<<num[N]<<endl;
        return 0;
    }
  • 相关阅读:
    20145305 《信息安全系统设计基础》第10周学习总结
    20145305 《信息安全系统设计基础》实验五 网络通信
    20145305 《信息安全系统设计基础》实验四 驱动程序设计
    20145304 《信息安全系统设计基础》课程总结
    20145304 《信息安全系统设计基础》第十四周学习总结
    计算机系统要素
    20145304 《信息安全系统设计基础》第十三周学习总结
    20145304 《信息安全系统设计基础》第十二周学习总结
    GDB调试汇编堆栈
    20145304 20145315 《信息安全系统设计基础》 实验五 网络通信
  • 原文地址:https://www.cnblogs.com/acgoto/p/8994123.html
Copyright © 2011-2022 走看看