• [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<<'
    ';
                }
    
                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;
    }
  • 相关阅读:
    陈应松《母亲》
    黄灯:一个农村儿媳眼中的乡村图景
    喝完茶为什么嘴里是甜的
    俗语一千条
    XtraBackup完整备份与增量备份的原理
    李嘉诚:90%考虑失败 关注细节
    redo和undo的区别
    tar命令
    自增锁引发的悲剧
    各版本 MySQL 并行复制的实现及优缺点
  • 原文地址:https://www.cnblogs.com/zeolim/p/12270595.html
Copyright © 2020-2023  润新知