โจทย์
กำหนด 3 จำนวนเต็มบวก a, b, c แต่ละขั้นตอนเลือก 2 ตัวที่ผลรวม > ตัวที่เหลือ ลบ 1 จากทั้งคู่ หาจำนวนขั้นตอนน้อยที่สุดทำให้ทั้ง 3 ตัวเป็น 0
ตัวอย่าง
a=4, b=4, c=6
(4,4,6) → ลบ a,b: (3,3,6)
→ ลบ a,c: (2,3,5)
→ ลบ a,c: (1,3,4)
→ ลบ a,c: (0,3,3)
→ ลบ b,c: (0,2,2)
→ ลบ b,c: (0,1,1)
→ ลบ b,c: (0,0,0)
Steps: 7
แนวคิด: Greedy + Math
เพื่อลดขั้นตอนให้น้อยที่สุด ควรลดตัวเลขใหญ่ๆ ก่อน กลยุทธ์:
- เรียง
a ≤ b ≤ c - ถ้า
a + b > c: ลด a,b พร้อมกันจนกว่า a=0 หรือ a+b=c - เหลือ
0, b', c'โดยc' = b'→ ลด b',c' พร้อมกันb'ครั้ง - รวม Steps =
min(a, b)(จากขั้นตอน 2) +b'(จากขั้นตอน 3)
สูตรทางคณิตศาสตร์
หลังเรียง a ≤ b ≤ c:
- ถ้า
a + b ≤ c: ตอบ =a + b(ลด a,b จน a=0 แล้วลด b,c) - ถ้า
a + b > c: ตอบ =(a + b + c) / 2(Integer division)
โค้ด C++
#include <bits/stdc++.h>
using namespace std;
int maxSteps(int a, int b, int c) {
// เรียง a ≤ b ≤ c
if (a > b) swap(a, b);
if (b > c) swap(b, c);
if (a > b) swap(a, b);
if (a + b <= c) {
return a + b;
} else {
return (a + b + c) / 2;
}
}
// วิธี Simulation (ช้ากว่า แต่เข้าใจง่าย)
int maxStepsSim(int a, int b, int c) {
int steps = 0;
while (true) {
// เรียงใหม่ทุกรอบ
if (a > b) swap(a, b);
if (b > c) swap(b, c);
if (a > b) swap(a, b);
if (a == 0 && b == 0) break;
if (a == 0) {
// เหลือ b,c → ลดคู่กัน
steps += b;
break;
}
// a > 0, b > 0
a--; b--; steps++;
}
return steps;
}
int main() {
cout << maxSteps(4, 4, 6) << endl; // 7
cout << maxSteps(2, 3, 10) << endl; // 5 (2+3=5 ≤ 10)
cout << maxSteps(5, 5, 5) << endl; // 7 ((5+5+5)/2 = 7)
cout << maxSteps(1, 1, 1) << endl; // 1
cout << maxSteps(10, 1, 1) << endl; // 2
// ทดสอบกับ Simulation
cout << "--- Simulation ---" << endl;
cout << maxStepsSim(4, 4, 6) << endl;
return 0;
}
การพิสูจน์สูตร
แต่ละขั้นตอนลดผลรวมรวม a+b+c ลง 2 (ลบ 1 จาก 2 ตัว)
- ถ้า
a+b ≤ c: ตัว c ใหญ่เกินกว่า ลด a,b จนหมด → Steps = a+b - ถ้า
a+b > c: สามารถลดจนหมดทั้ง 3 ได้ → Steps = floor((a+b+c)/2)
ผลลัพธ์
7 5 7 1 2 --- Simulation --- 7
สรุป
โจทย์นี้คือ LeetCode 1753 (Maximum Score From Removing Stones) ใช้ Greedy + Math ได้ O(1) ไม่ต้อง Simulation