473. Matchsticks to Square

题目: Remember the story of Little Match Girl? By now, you know exactly what matchsticks the little match girl has, please find out a way you can make one square by using up all those matchsticks. You should not break any stick, but you can link them up, and each matchstick must be used  exactly  one time.

Your input will be several matchsticks the girl has, represented with their stick length. Your output will either be true or false, to represent whether you could make one square using all the matchsticks the little match girl has.

大意就是用所有的火柴任意组合成4条边,看能不能组成一个正方形。

思路:首先算出火柴总共的长度,除以4如果不是整数就不用进行下面的运算,肯定不行。如果是整数,用这个整数记为edge进行判断的条件进行DFS。用一个大小为4的辅助空间a,存储每条边的长度。从数组的第一个元素开始DFS,如果该元素加上a中的元素没有超过edge,那么就加上,如果超过了,就加到a的下一个元素,然后对数组的下一个元素进行DFS。直到数组的最后一个元素被搜索之后,检查a中是否4条边都相等,如果相等就返回true,如果不等返回false,并且回溯,把a中的元素减掉当前搜索的数组元素。提交的时候,发现超时了,参考网上的做法,在DFS之前先对数组进行由大到小的排序。因为最终的边如果包含了较长的边,那么这条边肯定由较少小边组成,所以从较长的边开始搜索,很快就到达edge了,也就是会先剪更多的枝,减少时间。


class Solution {
public:
	bool makesquare(vector<int>& nums)
	{
		if (nums.size() < 4)
			return false;
		int sum = 0;
		for (int i = 0; i < nums.size(); ++i)
			sum += nums[i];
		if (sum % 4 != 0)
			return false;                        //先判断明显不可能的情况
		vector<int> temp(4, 0);
		sort(nums.rbegin(),nums.rend());//排序,至关重要
		return dfs(nums, temp, 0, sum / 4);
	}
	bool dfs(vector<int>& nums, vector<int>& a, int index, int edge)
	{
		if (nums.size() == index)   //检查是否能组成正方形
		{
			for (int i = 0; i < 3; ++i)
			{
				if (a[i] != a[i + 1])
				{
					return false;
				}
			}
			return true;
		}
		for (int i = 0; i < 4; ++i)
		{
			if (a[i] + nums[index] > edge)    //剪枝
				continue;
			a[i] += nums[index];
			if (dfs(nums, a, index + 1, edge))
				return true;
			a[i] -= nums[index];                 //回溯,还原状态
		}
		return false;
	}
};


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值