給定 n (≤ 20) 根木棒,長度為正整數。問能否用所有木棒拼成一個正方形(不可折斷)。
sum % 4 == 0,邊長 target = sum / 4。≤ target。將木棒降序排列,依次嘗試放入 4 條邊。
狀態:dfs(cur_len, start_idx, finished_sides)
- cur_len:當前正在拼的邊已湊到的長度
- start_idx:下一根木棒的搜索起始下標(避免排列重複)
- finished_sides:已拼好幾條邊(拼好 3 條第 4 條必成)
start_idx 往後找,避免同一邊內木棒順序排列重複。stick[i] == stick[i-1] 且 i-1 未被使用/嘗試失敗,直接跳過 i。target,無需驗證第 4 條。bool dfs(int cur_len, int start, int k) {
if (k == 3) return true; // 3 條拼好,第 4 條自動成形
if (cur_len == target) return dfs(0, 0, k + 1); // 開啟下一條邊
int prev = -1;
for (int i = start; i < n; ++i) {
if (vis[i] || cur_len + sticks[i] > target || sticks[i] == prev) continue;
vis[i] = true;
if (dfs(cur_len + sticks[i], i + 1, k)) return true;
vis[i] = false;
prev = sticks[i]; // 記錄本層嘗試失敗的長度
if (cur_len == 0) return false; // 關鍵:第一根木棒放不進去,對稱性失敗
}
return false;
}
n ≤ 20 且剪枝極強,實測毫秒級通過。k 為參數。n 較大但長度和較小,可用 DP 狀態壓縮。