• 正方形数组的数目(DFS,剪枝)


    题意

    给定一个包含\(N\)个非负整数数组\(A\),如果该数组每对相邻元素之和是一个完全平方数,则称这一数组为正方形数组。

    返回\(A\)的正方形排列的数目。

    两个排列\(A1\)\(A2\)不同的充要条件是存在某个索引\(i\),使得\(A1[i] \neq A2[i]\)

    题目链接:https://www.acwing.com/problem/content/4522/

    数据范围

    \(1 \leq N \leq 12\)

    思路

    假设所有的数字都是不同的,这种情况下方案数并不多,直接爆搜即可。

    但是如果有一些数是相同的,那么方案数就会多很多。正常的爆搜是无法通过的,因此考虑如何对这种情况剪枝。

    我们能够观察到一个性质,当某个位置枚举到某个数的时候,如果与这个数相同数值(下标小)的数之前被枚举过,那么再往后枚举就没有意义了,因为全都已经枚举过了。

    例如:[1 3 6 6 6 10]。爆搜出前2个数是[1 3],那么第3个数是哪个6都一样,因此枚举完下标是3的那个6之后,后面两个6可以直接跳过了。

    代码

    #include <iostream>
    #include <cstring>
    #include <algorithm>
    #include <cstdio>
    #include <cmath>
    
    using namespace std;
    
    const int N = 20;
    
    int n;
    int a[N], b[N];
    int ans;
    bool st[N];
    
    void dfs(int u)
    {
        if(u == n + 1) {
            ans ++;
            return;
        }
        for(int i = 1; i <= n; i ++) {
            if(st[i]) continue;
            int t = sqrt(a[i] + b[u - 1]);
            if(u > 1 && a[i] + b[u - 1] != t * t) continue;
            if(i > 1 && a[i] == a[i - 1] && !st[i - 1]) continue;
            st[i] = true;
            b[u] = a[i];
            dfs(u + 1);
            st[i] = false;
        }
    }
    
    int main()
    {
        scanf("%d", &n);
        for(int i = 1; i <= n; i ++) scanf("%d", &a[i]);
        sort(a + 1, a + n + 1);
        dfs(1);
        printf("%d\n", ans);
        return 0;
    }
    
  • 相关阅读:
    python实现Linux启动守护进程
    多维监控体系
    python 设计模式
    markdown安装和使用
    cobbler深入学习
    cobbler重装、web、定制化
    cobbler工作流分析
    cobbler安装、部署、测试
    Django中Celery的实现介绍(一)
    centos 搭建git服务器
  • 原文地址:https://www.cnblogs.com/miraclepbc/p/16489262.html
Copyright © 2020-2023  润新知