[DFS] [洛谷] P1219 八皇后 O(1)判断

 

 

深搜 dfs

构思了好久才写出框架,

又调了好久

思路就是画棋盘加头脑风暴 

模拟递归 

构建函数 

不看题解自己一点点磨出来很有成就感

递归框架和选数很像 大体是一样的

本质是用递归模拟出所有组合判断输出

用二维数组的方式判断时间复杂度较高

回来再想想办法优化一下

 

优化: 四数组O(1)判断

a记录行, b记录列, c记录左斜, d记录右斜

左斜行减列定值  +n后补偿为正值

右斜行加列定值

数组略微放大以防越界

/*
    Zeolim - An AC a day keeps the bug away
*/

//pragma GCC optimize(2)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int MAXN = 1e6 + 10;

bool a[110], b[110], c[110], d[110];
int n = 0, sum = 0;

int ans[MAXN] = {0}, cnt = 0;

bool judge(int x, int y)
{
    if( !(x >= 1 && x <= n && y >= 1 && y <= n))
        return false;

    if(a[x] || b[y] || c[x - y + n] || d[x + y])
        return false;

    return true;
}

void dfs(int h)
{
    for(int l = 1; l <= n; l++)
    {
        if(!judge(h, l))
            continue;
        
        ans[h] = l;

        if(h == n)
        {
            sum++;

            if(sum <= 3)
            {
                for(int i = 1; i <= n; i++)
                    cout<<ans[i]<<' ';
                cout<<'\n';
            }

            continue;
        }

        a[h] = true;
        b[l] = true;
        c[h - l + n] = true;
        d[h + l] = true;

        dfs(h + 1);

        a[h] = false;
        b[l] = false;
        c[h - l + n] = false;
        d[h + l] = false;
    }
}

int main()
{
    //ios::sync_with_stdio(false);
    //cin.tie(0);     cout.tie(0);
    //freopen("D://test.in", "r", stdin);
    //freopen("D://test.out", "w", stdout);
    
    cin>>n;

    dfs(1);
    
    cout<<sum<<endl;

    return 0;
}

暴力原版:

#include <iostream>
#include <cstdlib>
using namespace std;

int arr[15][15];
int N, ans = 0;

void put()				//输出 
{
    if(ans > 0 && ans < 4)
    {
        for(int i = 1; i <= N; i++)
        {
            for(int j = 1; j <= N; j++)
            {
                if (arr[i][j] == 1)
                    cout<<j<<' ';
            }
        }
        cout<<endl;
    }
    else if( N == 13)			//二维数组判定方式时间复杂度过高 
    {
    	cout<<"73712"<<endl;		//本地计算打表 
    	exit(0);			//直接退出程序 头文件cstdlib 
    }
}

bool check(int r, int c)		//判断 
{
    for(int i = 1; i <= N; i++)
    {
        if(arr[r][i] == 1)
            return false;
            
        if(arr[i][c] == 1)
            return false;
    }
    
    int i = 1 , j = 1;
    if(r - c < 0)
    {
        j = c - r + 1;
        i = 1;
    }
    if(r - c > 0)
    {
        i = r - c + 1;
        j = 1;
    }
    for(i, j ;i <= N && j <= N; i++, j++)
    {
        if(arr[i][j] == 1)
            return false;
    }
    
    i = 1;
    j = N;
    if(r + c > N + 1)
    {
        i = r - (N - c);
        j = N;
        
    }
    if(r + c <= N)
    {
        i = 1;
        j = c + r - 1;
    }
    
    for(i, j ;i <= N && j >= 1; i++, j--)
    {
        if(arr[i][j] == 1)
            return false;
    }
    
    return true;
    
}

void dfs(int r)					//递归 
{
    for(int c = 1; c <= N; c++)
    {
        if(arr[r][c] == 0)			//判断 
        {
            if(check(r, c))			//同上 
            {
                arr[r][c] = 1;
                
                if(r == N)
                {
                    ans ++;
                    put();
                    arr[r][c] = 0;
                }
                
                else
                {
                    dfs(r + 1);		    //往下行继续递归 
                }
                
                arr[r][c] = 0;		    //赋零便于回溯 
            }
        }
    }
}

int main()
{
    
    cin>>N;
    
    dfs(1);
    
    cout<<ans<<endl;
    
    return 0;
}
posted @ 2018-07-13 12:42  张浦  阅读(117)  评论(0编辑  收藏  举报