Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> C++

ปัญหาการแบ่งพาร์ติชันใน C++

ในปัญหานี้ เราต้องสร้างโค้ด C++ เพื่อตรวจสอบว่าอาร์เรย์สามารถแบ่งเป็นสองเซตย่อยที่มีผลรวมเท่ากันได้หรือไม่ นอกจากนี้ยังต้องตรวจสอบเงื่อนไขว่าผลรวมขององค์ประกอบในทั้งสองเซตย่อยเท่ากันจริงหรือไม่ ปัญหาการแบ่งพาร์ติชันเป็นรูปแบบหนึ่งของปัญหา Subset Sum Problem ซึ่งเป็นรูปแบบหนึ่งของ Knapsack Problem เราจะใช้ภาษา C++ ในการแก้ปัญหานี้ ต้องคืนค่าสตริง "Yes" หรือ "No" ขึ้นอยู่กับว่าเงื่อนไขเป็นจริงหรือไม่

ข้อมูลนำเข้า

arr[] = {6, 4, 8, 12, 15}

ข้อมูลส่งออก

Is possible to divide into two subsets of equal sum

แนวทางการแก้ปัญหา

เป้าหมายคือหาผลรวมของทุกองค์ประกอบในเซต เมื่อผลรวมของอาร์เรย์เป็นคี่ เราไม่สามารถแบ่งเป็นสองเซตได้ ระบุเซตย่อยที่มีผลรวม sum/2 เมื่อผลรวมเป็นคู่ ใช้งานอาร์เรย์ที่กำหนด ตรวจสอบองค์ประกอบแต่ละตัวทีละตัว แล้วเลือกหนึ่งในสองทางเลือก:

  • รวมองค์ประกอบปัจจุบันในเซตย่อย แล้วเพิ่มส่วนที่เหลือเพื่อให้ได้ผลรวม
  • นำองค์ประกอบปัจจุบันออกจากเซตย่อย แล้วทำซ้ำกับองค์ประกอบอื่นๆ

สุดท้าย คืนค่า true ถ้าองค์ประกอบปัจจุบันถูกรวมหรือไม่อยู่ในเซตย่อย มิฉะนั้นคืนค่า false การเรียกซ้ำจะสิ้นสุดเมื่อไม่มีองค์ประกอบเหลือ หรือผลรวมติดลบ ในกรณีที่ผลรวมเป็น 0 เราคืนค่า true หมายถึงพบเซตย่อยแล้ว

ตัวอย่างโค้ด (วิธีเรียกซ้ำ)

#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: Dynamic Programming

เมื่อผลรวมขององค์ประกอบไม่มากเกินไป ปัญหานี้สามารถแก้ได้ด้วย Dynamic Programming สร้างอาร์เรย์ 2D part[][] ขนาด (sum/2 + 1)*(n+1) สร้างคำตอบแบบ bottom-up โดยแต่ละค่าที่เติมมีคุณสมบัติดังนี้ เราสามารถแก้ปัญหานี้ด้วยอาร์เรย์ 2D ขนาด (sum/2 + 1)*(n + 1) แทนที่จะเป็นขนาด (sum/2 + 1)*(n + 1)

ตัวอย่างโค้ด (Dynamic Programming)

#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++ โค้ดนี้สามารถเขียนใน Java, Python และภาษาอื่นๆ ได้ เราแก้ปัญหาการแบ่งพาร์ติชันโดยใช้การเรียกซ้ำและอาร์เรย์ในภาษา C++ เป็นโค้ดพื้นฐานแต่มีประโยชน์มากในการแก้ปัญหาต่างๆ