AcWing每日一题 2022.7.19
DFS + 排序剪枝
排序剪枝:为了防止同一个序列被枚举多次,先排序,对于相同的数,只枚举出现的第一次。
对于dfs内部的排序,同样只枚举出现的第一次,但是是对于本次枚举出现的第一次,之前已经确定在序列中的不需要考虑。
由于每次枚举只考虑最先出现的那个,所以这个结构是可以迭代执行而不出错的。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 20;
int n;
int a[N];
int st[N];
LL ans;
bool judge(int x) {
if ((int)sqrt(x) * (int)sqrt(x) == x)
return true;
return false;
}
void dfs(int p, int pre) {
if (p >= n) {
ans++;
return ;
}
for (int i = 1; i <= n; i++) {
if (!st[i]) {
if (i > 1 && !st[i - 1] && a[i] == a[i - 1])
continue;
if (judge(a[pre] + a[i])) {
st[i] = 1;
dfs(p + 1, i);
st[i] = 0;
}
}
}
return ;
}
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
sort(a + 1, a + 1 + n);
for (int i = 1; i <= n; i++) {
if (i > 1 && a[i] == a[i - 1])
continue;
st[i] = 1;
dfs(1, i);
st[i] = 0;
}
printf("%lld\n", ans);
return 0;
}