ในปัญหานี้ เราต้องสร้างโค้ด C++ เพื่อกำหนดว่าอาร์เรย์สามารถแบ่งออกเป็นสองอาร์เรย์ย่อยที่เท่ากันหรือไม่ นอกจากนี้ เราต้องตรวจสอบเงื่อนไขด้วยว่าผลรวมขององค์ประกอบทั้งหมดในอาร์เรย์ย่อยทั้งสองเหมือนกันหรือไม่ ปัญหาการแบ่งพาร์ติชั่นเป็นตัวแปรของ Subset Sum Problem ซึ่งในทางกลับกัน ปัญหาของเป้ เราจะใช้ภาษาการเขียนโปรแกรม C++ เพื่อจัดการกับปัญหาพาร์ติชั่น เราต้องส่งคืนสตริงที่มีใช่หรือไม่ใช่ขึ้นอยู่กับว่าเงื่อนไขที่ระบุเป็นจริงหรือไม่
ป้อนข้อมูล
arr[] = {6, 4, 8, 12, 15}
ผลผลิต
Is possible to divide into two subsets of equal sum
แนวทางการแก้ปัญหา
เป้าหมายคือการหาผลรวมขององค์ประกอบทั้งหมดในชุด เมื่อผลรวมอาร์เรย์เป็นเลขคี่ เราไม่สามารถแบ่งออกเป็นสองชุดได้ ระบุเซตย่อยด้วย sum/2 เมื่อผลรวมเป็นคู่ ใช้อาร์เรย์ที่กำหนด ตรวจสอบแต่ละองค์ประกอบทีละรายการ แล้วเลือกตัวเลือกใดตัวเลือกหนึ่งต่อไปนี้:
-
รวมรายการปัจจุบันในชุดย่อยต่อไป จากนั้นเพิ่มส่วนที่เหลือเพื่อให้ได้ยอดรวม
-
เมื่อรายการปัจจุบันถูกลบออกจากชุดย่อยแล้ว ให้ทำซ้ำขั้นตอนสำหรับรายการอื่นๆ
สุดท้าย คืนค่า จริง หากรายการปัจจุบันถูกรวมหรือไม่รวมในชุดย่อย มิฉะนั้นให้คืนค่าเท็จ การเรียกซ้ำจะสิ้นสุดลง หากไม่มีรายการเพิ่มเติมหรือหากผลรวมกลายเป็นลบ ในกรณีของผลรวมเป็น 0 เราจะคืนค่า จริง หมายความว่ามีการระบุเซตย่อยแล้ว
ตัวอย่าง
#include <bits/stdc++.h> using namespace std; bool isSubsetSum(int arr[], int n, int sum) { if (sum == 0) return true; if (n == 0 && sum != 0) return false; if (arr[n - 1] > sum) return isSubsetSum(arr, n - 1, sum); return isSubsetSum(arr, n - 1, sum) || isSubsetSum(arr, n - 1, sum - arr[n - 1]); } bool findPartiion(int arr[], int n) { int sum = 0; for (int i = 0; i < n; i++) sum += arr[i]; if (sum % 2 != 0) return false; return isSubsetSum(arr, n, sum / 2); } int main() { int arr[] = { 6, 4, 8, 12, 15 }; int n = sizeof(arr) / sizeof(arr[0]); if (findPartiion(arr, n) == true) cout << "Is possible to divide into two subsets " "of equal sum"; else cout << "Is impossible to divide into two subsets" " of equal sum"; return 0; }
ผลลัพธ์
Is impossible to divide into two subsets of equal sum
แนวทางที่ 2
เมื่อส่วนประกอบทั้งหมดไม่ใหญ่เกินไป ปัญหาสามารถจัดการได้โดยใช้โปรแกรมแบบไดนามิก สามารถสร้างส่วนอาร์เรย์ 2 มิติ[][]ขนาด (ผลรวม/2 + 1)*(n+1) ได้ เราอาจสร้างวิธีแก้ปัญหาจากล่างขึ้นบน เพื่อให้แต่ละรายการที่กรอกมีคุณสมบัติดังต่อไปนี้ เราสามารถแก้ปัญหานี้ได้โดยใช้อาร์เรย์ขนาด 2 มิติ (ผลรวม/2 + 1)*(n + 1) แทน ขนาดอาร์เรย์ 2 มิติ (ผลรวม/2 + 1)*(n + 1).
ตัวอย่าง
#include <bits/stdc++.h> using namespace std; bool findPartiion(int arr[], int n) { int sum = 0; int i, j; for (i = 0; i < n; i++) sum += arr[i]; if (sum % 2 != 0) return false; bool part[sum / 2 + 1]; for (i = 0; i <= sum / 2; i++) { part[i] = 0; } for (i = 0; i < n; i++) { for (j = sum / 2; j >= arr[i]; j--){ if (part[j - arr[i]] == 1 || j == arr[i]) part[j] = 1; } } return part[sum / 2]; } int main() { int arr[] = { 6, 4, 8, 12, 15 }; int n = sizeof(arr) / sizeof(arr[0]); if (findPartiion(arr, n) == true) cout << "Is possible to divide into two subsets of equal " "sum"; else cout << "Is impossible to divide into two subsets" " of equal sum"; return 0; }
ผลลัพธ์
Is impossible to divide into two subsets of equal sum
บทสรุป
ในปัญหานี้ เราได้เรียนรู้วิธีแก้ปัญหาพาร์ติชั่นพร้อมกับโค้ด c++ รหัสนี้ยังสามารถเขียนในภาษาจาวา ไพธอน และภาษาอื่นๆ ได้อีกด้วย เราได้แก้ไขปัญหาพาร์ติชั่นโดยใช้อาร์เรย์แบบเรียกซ้ำในภาษาการเขียนโปรแกรม C++ เป็นรหัสพื้นฐานแต่มีประโยชน์มากมายในการแก้ปัญหา