跳棋的挑战

呃呃,这题是一道经典的DFS题,就是个8皇后啊。
因为本人心虚,赶脚写的代码有点慢,就打了个表。
咳咳咳,说正题,这题说每行,每列,每斜边都至多有一个旗子,这不就是8皇后的标准题目吗,8皇后大家总会写吧。
恩,如果大家连把皇后都不会写的话,那就接着往下看。
先看一下8皇后的原题:
在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法.
用深搜就可以解决了,先枚举每一行,然后判断能不能放,如果能放,就先放着,递归调用一下,等回溯的时候再拿起来。
关于这个判断能不能放,还有一点小技巧,行和列当然都很简单,但是斜行就不同了,斜行分两条,一条从左往右,一条从右往左,这里就直说了,这两条分别可以这样表示:

x1[deep-i+20] = 1,x2[deep+i] = 1

上代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>

int ans,n,l[100],x1[100],x2[100],ans1[100],ans2[100] = {4,40,92,352,724,2680,14200,73712};

void print()
{
    if(ans>3)return;
    for(int i = 0;i<n;i++)std::cout<<ans1[i]+1<<" ";
    std::cout<<std::endl;
}

void get_ans(int deep)
{
    if(ans==3)return;
    if(deep==n){ans++;print();return;}
    for(int i = 0;i<n;i++)
    {
        if(l[i]==1||x1[deep-i+20]==1||x2[i+deep]==1)continue;
        l[i] = 1;x1[deep-i+20] = 1;x2[deep+i] = 1;ans1[deep] = i;
//      for(int i = 0;i<n;i++)std::cout<<l[i]<<" ";
//      std::cout<<std::endl; 
        get_ans(deep+1);
        l[i] = 0;x1[deep-i+20] = 0;x2[deep+i] = 0;
    }
}

int main()
{
    freopen("checker.in","r",stdin);
    freopen("checker.out","w",stdout);
    std::cin>>n;
    get_ans(0);
    std::cout<<ans2[n-6];
    fclose(stdin);
    fclose(stdout);
    return 0;
}
posted @ 2017-06-08 20:20  leo101  阅读(202)  评论(0编辑  收藏  举报