1. 程式人生 > >Leetcode程式設計練習:火柴匹配

Leetcode程式設計練習:火柴匹配

題目原文:(id=473)

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.

Example 1:
Input: [1,1,2,2,2]
Output: true

Explanation:
You can form a square with length 2, one side of the square came two sticks with length 1.

Example 2:

Input: [3,3,3,3,4]
Output: false

Explanation: You cannot find a way to form a square with all the matchsticks.

給定若干根火柴的長度,問是否可以用這些火柴剛好拼出正方形,簡單來講就是把一個數列分成和相等的4組數字。一開始考慮過想用分成兩組的動態規劃的方法,但發現有很大的問題,分成兩組那道題還有數字個數相同的限制,而四組數字的個數是隨意的。可行的解法只想到直接搜尋一種,但是直接列舉的話運算量太大,會超時,所以仍需要適當的剪枝:

  • 如果數字的和不為4的倍數則不用搜索
  • 對於一個元素,當有2個組的數字和目前相等的話,只用搜尋加入其中一組的情況
class Solution {
public:
    bool makesquare(vector<int>& nums) {
		int n = nums.size();
		if (n < 4) return false;
		int sol = 0;
		for (int i = 0;i < n;i++)
			sol += nums[i];
		if (sol % 4) return false;
		sol /= 4;
		vector<int> sum(4, 0);
		return dfs(nums, sum, 0, sol);
	}
	bool dfs(vector<int>& nums, vector<int>& sum, int i, int sol) {
		if (i == nums.size()) {
			if (sum[0] == sol&&sum[1] == sol&&sum[2] == sol)
				return true;
			return true;
		}
		for (int j = 0;j < 4;j++) {
			if (sum[j] + nums[i] <= sol) {
				if (j>0&&sum[j-1]==sum[j]) continue;
				sum[j] += nums[i];
				if (dfs(nums, sum, i + 1, sol)) return true;
				sum[j] -= nums[i];
			}
		}
		return false;
	}
};