题目
给定一个非负整数数组 A A A,如果该数组每对相邻元素之和是一个完全平方数,则称这一数组为正方形数组。
返回 A A A 的正方形排列的数目。
两个排列 A 1 A1 A1 和 A 2 A2 A2 不同的充要条件是存在某个索引 i i i,使得 A 1 [ i ] ≠ A 2 [ i ] A1[i] \neq A2[i] A1[i]=A2[i]。
输入格式
第一行包含一个整数 n n n,表示数组 A A A 的长度。
第二行包含 n n n 个整数 A [ i ] A[i] A[i]。
输出格式
一个整数,表示 A A A 的正方形排列的数目。
数据范围
1
≤
n
≤
12
1 \le n \le 12
1≤n≤12,
0
≤
A
[
i
]
≤
1
0
9
0 \le A[i] \le 10^9
0≤A[i]≤109。
输入样例:
3
1 17 8
输出样例:
2
样例解释
[ 1 , 8 , 17 ] [1,8,17] [1,8,17] 和 [ 17 , 8 , 1 ] [17,8,1] [17,8,1] 都是有效的排列。
思路:使用DFS() 注意使用全排列会有重复
solution1 : 使用set()进行去重,然后在进行判断
solution2 :直接进行得到最终的cnt,然后用 假设原来有6个0,6个1,计算得到cnt=74,649,600 那么直接用 74,649,600/6!/6! = 144 ,得到cnt=144
但是没有通过
说明我们不能取完全部的排列,要剪枝
怎么减?
假如我们规定好在相同的数字中,索引小的一定排在前面,那么就不会有重复了。
from itertools import permutations as per
import math
N = int(input())
s = [0] + list(map(int,input().split()))
d = dict()
for i in s:
if i in d.keys():
d[i] += 1
else:d[i] = 1
state = [ False for i in range(N+1)]
def judge(string,i,x):
if (int(x) - int(math.sqrt(int(x)))*int(math.sqrt(int(x))))>1e-5 :return False
else:
for x in string:
if s[i] == s[x] and i<x:return False
#print(string,i)
return True
cnt = 0
def DFS(string,n,last):
global N,cnt
if n == N+1:
cnt+=1;return
for i in range(1,N+1):
if (n==1) or (not state[i] and n>1 and judge(string,i,s[i] + last)):
state[i] = True
DFS(string+[i],n+1,s[i])
state[i] = False
string = []
DFS(string,1,0)
'''
fact = [ 1 for i in range(13)]
for i in range(1,13):
fact[i] = fact[i-1]*i
for i in d.values():
cnt//=fact[i]
'''
print(cnt)
就可以AC了