zoukankan      html  css  js  c++  java
  • 八皇后(弱版)

    今天教你如何O2水过八皇后...

    题目:

    检查一个如下的6 x 6的跳棋棋盘,有六个棋子被放置在棋盘上,使得每行、每列有且只有一个,每条对角线(包括两条主对角线的所有平行线)上至多有一个棋子。

    上面的布局可以用序列2 4 6 1 3 5来描述,第i个数字表示在第i行的相应位置有一个棋子,如下:

    行号 1 2 3 4 5 6

    列号 2 4 6 1 3 5

    这只是跳棋放置的一个解。请编一个程序找出所有跳棋放置的解。并把它们以上面的序列方法输出。解按字典顺序排列。请输出前3个解。最后一行是解的总个数。

    这道题为明显的深搜题,具体算法...暴力枚举每一个合法的位置组合,(横)坐标从小到大遍历可保证字典序问题

    结合具体代码分析思路:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    int n;
    int used[15][15];
    int q[15];
    int t;
    int tim;
    inline void search(int pos){for(int i=1;i<=n;i++){
            if(!used[i][pos]){
                t++;
                q[t]=i;
                if(t==n){
                    tim++;
                    if(tim<=3){
                        for(int j=1;j<=n;j++)
                            printf("%d ",q[j]);
                        puts("");
                    }
                }
                else{
                    for(int j=1;j<=n;j++){
                        used[j][pos]++;
                        used[i][j]++;
                    }
                    for(int j=max(pos+i-n,1);j<=min(pos+i-1,n);j++)
                        used[j][pos+i-j]++;
                    for(int j=max(pos-i+1,1),t=max(i-pos+1,1);j<=min(pos-i+n,n);j++,t++)
                        used[t][j]++;
                    search(pos+1);
                    for(int j=1;j<=n;j++){
                        used[j][pos]--;
                        used[i][j]--;
                    }
                    for(int j=max(pos+i-n,1);j<=min(pos+i-1,n);j++)
                        used[j][pos+i-j]--;
                    for(int j=max(pos-i+1,1),t=max(i-pos+1,1);j<=min(pos-i+n,n);j++,t++)
                        used[t][j]--;
                }
                t--;
            }
        }
    }
    int main(){
        scanf("%d",&n);
        search(1);
        printf("%d",tim);
        return 0;
    }

    利用used数组保存地图状态,如果不为0即为使用,注意该数组不能用bool,因为多个皇后的势力范围一定会出现覆盖,如果用bool则会在回溯操作时将不该删除的其他皇后势力范围删掉,使用int进行逐层覆盖即可,

    关于每个皇后势力范围划分问题,也就是如何根据皇后坐标找对角线的问题,建议画一个图自己去推,很锻炼模拟能力,

    至于本代码中pos与i哪个是横坐标哪个是纵坐标...我好像也不知道...在推导皇后势力范围公式时搞反了,导致两变量所处位置与思路中完全不符,然而这并没有关系,因为本题中棋盘为正方形,可以将横纵坐标反过来,也许思路想对横坐标进行搜索枚举,最终也仅是将纵坐标当做结果输出即可

    最后,search函数搜索主程序后面的t--必不可少,它是回溯操作的关键,即删去原添加坐标的序号,表示未进行该操作。

    再说一下关于时间限制的问题(开O2):

    不用inline的时间:

    444ms

    用了inline的时间:

    443ms

    (显然inline要快嘛~)

    不开O2就会突破天际直奔2000ms

    正经考试中这种算法不开O2在该数据范围内仅会WA一个点,还是相当划算的,不过13分没了

    6.13update

    其实这题不用非常麻烦的赋值语句,把used一个一个赋值,只需开个以为数组并找到合适的标识(比如与y轴的焦点纵坐标)来表示行,列,对角线,就能非常容易地标识使用路径,比无脑赋值效率高太多

    至于为什么不写代码...去看6.13的博客去

  • 相关阅读:
    vs.net2003里添加邮件发件人身份验证
    Linux下用PYTHON查找同名进程
    修改机器名后要修改IIS匿名访问用户
    [C#]使用MYSQL数据库
    JIRA OutOfMemoryErrors
    获取linux下当机堆栈
    python调用pipe
    [探讨]一次性工具软件
    GGSN
    三层交换机的作用
  • 原文地址:https://www.cnblogs.com/648-233/p/10964300.html
Copyright © 2011-2022 走看看