思路:
回溯題基本寫法。
- 用
multiset<int>
去記錄數字的使用情況。 - 用
set<vector<int>>
去重。 - 剪枝:雖然數字可以重複使用(如果有的話),但是每一層的數字不應出現重複枚舉。
比如:
2 2 2 2 2
每一層都應該放只能放2,而不是對2這個數字進行多次搜索。
class Solution {
public:
multiset<int> nums;
set<vector<int>> res;
int len ;
int numSquarefulPerms(vector<int>& A) {
len = A.size();
for(int x:A){
nums.insert(x);
}
vector<int> list;
dfs(0,list,A);
return res.size();
}
void dfs(int dpt,vector<int> &list,vector<int>& A){
if(dpt == len){
res.insert(list);
return;
}
unordered_set<int> optional;
for(int x:A){
if(nums.count(x)){
if( dpt<1 || check(x+list[dpt-1])){
optional.insert(x);
}
}
}
for(unordered_set<int>::iterator it=optional.begin();it!=optional.end();it++){
int x = *it;
list.push_back(x);
nums.erase(nums.find(x));
dfs(dpt+1,list,A);
list.pop_back();
nums.insert(x);
}
}
bool check(int x){
int r = int(sqrt(x)+0.5);
return x == r*r;
}
};