473. 火柴拼正方形
还记得童话《卖火柴的小女孩》吗?现在,你知道小女孩有多少根火柴,请找出一种能使用所有火柴拼成一个正方形的方法。不能折断火柴,可以把火柴连接起来,并且每根火柴都要用到。
输入为小女孩拥有火柴的数目,每根火柴用其长度表示。输出即为是否能用所有的火柴拼成正方形。
示例 1:
1 2
| 输入: [1,1,2,2,2] 输出: true
|
解释: 能拼成一个边长为2的正方形,每边两根火柴。
示例 2:
1 2
| 输入: [3,3,3,3,4] 输出: false
|
解释: 不能用所有火柴拼成一个正方形。
注意:
给定的火柴长度和在 0 到 10^9之间。火柴数组的长度不超过15。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| class Solution { public: int part; vector<bool> vis; bool f = true; bool makesquare(vector<int>& nums) { int sum = 0; for(int i = 0; i < nums.size(); i++) sum += nums[i]; if(!sum || sum%4) return false; part = sum / 4; vis = vector<bool>(nums.size()); //从大到小枚举所有边 sort(nums.begin(),nums.end(),greater<int>()); return dfs(nums,0,0,part); } //u:当前选了几个数,sum:当前的和,k:选到了第几层 bool dfs(vector<int> &nums,int u,int cur,int length){ if(cur == length) u+=1,cur=0; if(u == 4) return true; for(int i = 0; i < nums.size(); i++){ // if(!vis[i] && cur+nums[i] <= length){ vis[i] = true; if(dfs(nums,u,cur+nums[i],length)) return true; vis[i] = false; //如果当前木棒拼接失败,并且是第一个,则剪掉。 if(cur == 0) return false; //如果当前木棒拼接失败,并且是最后一个,则剪掉。 if(cur + nums[i] == length) return false; //如果当前木棒拼接失败,跳过所有相同长度的木棒。 while(i+1 < nums.size() && nums[i] == nums[i+1]) i++; } } return false; } };
|
思路:
剪枝策略:
- 从小到大枚举所有边
- 每条边内部的木棒长度规定为从大到小
- 如果当前木棒拼接失败,则跳过接下来所有长度相同的木棒。
- 如果当前木棒拼接失败,且是当前边的第一个,则直接剪掉当前分支。
- 如果当前木棒拼接失败,且是当前边的最后一个,则直接剪掉当前分支。