回溯法的求解過程實質上是乙個先序遍歷一棵狀態樹的過程,只是這棵樹不是遍歷前預先建立的,而是隱含在遍歷的過程中。
遞迴題的解法:首先把題目的決策樹畫出來,樹的層就是for迴圈,樹的深度就是要遞迴的引數i。畫出決策樹後,找規律,進行剪枝。e.g.輸入【1, 1, 2, 2, 2】
放小球問題,總共四個盒子,每個數從大到小依次網盒子裡放,放滿則放到下乙個盒子。
首先將所有的數進行從大到小排序,先放大的,後放小的。
樹層為四個盒子,樹的深度為每個數。
// 正方形的四條邊恰好相當於四個盒子,然後依次向每個盒子裡面放入給定小球,如果乙個盒子放滿了則放到下乙個盒子裡。
bool
addstick
(int i,
const std::vector<
int>
& nums,
int target_side_len,
int side_sums[4]
)return
false;}
for(
int j =
0; j <4;
++j)
side_sums[j]
+= nums[i]
;// 在當前的盒子放入下乙個數if(
addstick
(i +
1, nums, target_side_len, side_sums)
)// 嘗試完這個數恢復之前的狀態, 然後放入下乙個盒子。
side_sums[j]
-= nums[i];}
return
false;}
bool
makesquare1
(std::vector<
int> nums)
// 對於遞迴在題目中提前找到剪枝條件十分重要。
int sum = std::
accumulate
(nums.
begin()
, nums.
end(),
0);if
(sum %4!=
0)int side_length = sum /4;
for(
int num : nums)
}// 由大到小排序,該條件至關重要。
// 由大到小排序後,可以極大地減少遞迴的次數。
std::
sort
(nums.
begin()
, nums.
end(
), std::greater<
int>()
);int side_sums[4]
=;return
addstick(0
, nums, side_length, side_sums);}
intmain()
)<< std::endl;
std::cout <<
makesquare1()
<< std::endl;
std::cout <<
makesquare1()
<< std::endl;
std::cout <<
makesquare1()
<< std::endl;
return0;
}
LeetCode 473 火柴拼正方形
還記得童話 賣火柴的小女孩 嗎?現在,你知道小女孩有多少根火柴,請找出一種能使用所有火柴拼成乙個正方形的方法。不能折斷火柴,可以把火柴連線起來,並且每根火柴都要用到。輸入為小女孩擁有火柴的數目,每根火柴用其長度表示。輸出即為是否能用所有的火柴拼成正方形 我看到題目,很快就想到了等分k份陣列這道題目....
LeetCode 473 火柴拼正方形 C
還記得童話 賣火柴的小女孩 嗎?現在,你知道小女孩有多少根火柴,請找出一種能使用所有火柴拼成乙個正方形的方法。不能折斷火柴,可以把火柴連線起來,並且每根火柴都要用到。輸入為小女孩擁有火柴的數目,每根火柴用其長度表示。輸出即為是否能用所有的火柴拼成正方形。示例 1 輸入 1,1,2,2,2 輸出 tr...
473 火柴拼正方形
還記得童話 賣火柴的小女孩 嗎?現在,你知道小女孩有多少根火柴,請找出一種能使用所有火柴拼成乙個正方形的方法。不能折斷火柴,可以把火柴連線起來,並且每根火柴都要用到。輸入為小女孩擁有火柴的數目,每根火柴用其長度表示。輸出即為是否能用所有的火柴拼成正方形。示例 1 輸入 1,1,2,2,2 輸出 tr...