1.深搜回溯
深搜:对每一个单位枚举它的每一种可能
回溯:当前决策无解时返回上一次决策的状态
原题
最基本的枚举:每根火柴分别放在四个边,N根火柴共枚举4^N次,很可能超时
优化
if(nums.size()<4) return false;//只有0-3根火柴,不可能拼成正方形
int sum=0;
for(auto x:nums) {
sum+=x;
t.push_back(0);
}
if(sum%4!=0) return false;//周长不是4的倍数,不可能
tar=sum/4;
//从大到小枚举每根火柴,可以去掉很多重复的情况
sort(nums.begin(),nums.end(),[](int a,int b){return a>b;});
if(nums[0]>tar) return false;//有单根火柴的长度比边长还长,不可能
下面开始进行搜索与回溯
每次只填充一条边,成功4次则说明可以
bool dfs(vector<int> nums,int i,int res,int n){
if(n==0) return true;//已完成4次
if(res==0) return dfs(nums,0,tar,n-1);//当前已完成,搜索下一次
for(int j=i;j<nums.size();j++){//i代表上一层已经搜到的边,只需从i往后搜
if(t[j]==0&&nums[j]<=res){
t[j]=1;//t[j]=1代表j号火柴已使用
if(dfs(nums,j,res-nums[j],n)) return true;//搜索下一个
t[j]=0;//运行到这里说明选择j号的所有策略都已经失败,此时丢弃j号(回溯)
//如果j号火柴被证明了不能使用,那么j号以后的、和j一样长的都不可能使用
while(j+1<nums.size()&&nums[j+1]==nums[j]) j++;
}
}
return false;
}
代码采取的优化有:
进行搜索与回溯之前删掉的情况
从大到小按顺序搜索
使用变量i删去0-i的搜索项
一根火柴不能用,这根火柴后面的,一样长的都不能用
以下分别是几次优化后的提交结果