首頁 >後端開發 >C++ >集合劃分是NP完全的

集合劃分是NP完全的

王林
王林轉載
2023-09-05 15:17:061405瀏覽

集合劃分是NP完全的

將包裹集合問題(Set Parcel)翻譯成中文,這是一個NP完全問題,任務是確定給定的一組正整數是否可以分成兩個子集,使得它們的總和相等。 NP完全意味著目前沒有已知的多項式時間演算法能夠解決所有情況,而驗證一個可能的解決方案應該可以在多項式時間內完成。許多其他的NP完全問題可以歸約到Set Parcel問題,顯示它的計算複雜性以及在理解更廣泛的NP完全問題類別中的重要性。由於其複雜性,解決Set Parcel問題的大規模案例可能需要龐大的時間投入,這使得有效地找到最佳解決方案變得困難。

Methods Used

  • Brute Force

  • 回溯演算法

Brute Force

暴力破解是一種直接而無辜的演算法方法,用於透過評估每一種可能的排列並選擇正確的排列來解決問題。它包括有效率地列舉每一種可能的排列,並實際檢查每種排列是否滿足問題的要求。雖然暴力破解方法在思路上簡單易懂且易於實施,但對於具有龐大排列空間的問題來說,它可能計算效率低且不切實際

Regardless of its straightforwardness, savage power can be a substantial methodology for issues with little info sizes or when the arrangement space is generally little and reasonable. It is regularular patterned for ue), sue, s刑, conve 是, 周圍, 是 consue, ” 是 ” 是 conjwards s regular, consection, sue. beginning stage prior to applying more modern calculations.

Algorithm

  • 計算集合中所有元件的完整性,並檢查它們是否可以被2整除。如果不能,返回"無解"。

  • Initialize two purge sets, subset1 and subset2.

  • 呼叫遞歸工作分割助理 partitionHelper,使用起始集合 S,子集 1,子集 2 和目標整體(totalSum / 2)

  • 在partitionHelper函數中:
  • Check on the off chance that the entirety of components in subset 1 is equal to the target whole. On the off chance that so, print subsets 1 and 2, and return. 如果集合S是清除的,則傳回 Choose component x from S and expel it from S.

  • Try including x in subset1 and calling partitionHelper recursively with the upgraded S, subset1, subset2, and the target sum.

  • 如果叫牌沒有發現一個大的包裹,從子集1中排除x並嘗試將x包含在子集2中
  • 使用重組後的S、子集1、子集2和目標總和遞歸來呼叫partitionHelper函數

  • If no substantial segment is found amid the recursion, print "No arrangement."

Example

#include <iostream>
#include <vector>

bool partitionHelper(std::vector<int> S, std::vector<int>& 
subset1, std::vector<int>& subset2, int targetSum) {
   if (targetSum == 0) {
      std::cout << "Subset 1: ";
      for (int num : subset1) {
         std::cout << num << " ";
      }
      std::cout << "\nSubset 2: ";
      for (int num : subset2) {
         std::cout << num << " ";
      }
      return true;
   }

   if (S.empty()) {
      return false;
   }

   int x = S.back();
   S.pop_back();

   subset1.push_back(x);
   if (partitionHelper(S, subset1, subset2, targetSum - x)) {
      return true;
   }
   subset1.pop_back();

   subset2.push_back(x);
   if (partitionHelper(S, subset1, subset2, targetSum - x)) {
      return true;
   }
   subset2.pop_back();

   return false;
}

void partition(const std::vector<int>& S) {
   int totalSum = 0;
   for (int num : S) {
      totalSum += num;
   }
   if (totalSum % 2 != 0) {
      std::cout << "No solution.\n";
      return;
   }

   std::vector<int> subset1, subset2;
   int targetSum = totalSum / 2;

   if (!partitionHelper(S, subset1, subset2, targetSum)) {
      std::cout << "No solution.\n";
   }
}

int main() {
   std::vector<int> set = {1, 2, 3, 4, 5, 6};
   partition(set);
   return 0;
}

輸出

No solution.

Backtracking

Backtracking is an overall algorithmic method used to look for answers for combinatorial issues deliberately. It is a type of experimentation search where the calculation investigates various conceivable outcomes, steadily constructing a possible arrangement and backtracks when it understands that the ebb and flow way can't prompt a substantial arrangement.

回溯系統可以被想像成一個調查樹,其中每個節點代表在特定步驟上做出的決策,而分支代表該決策的潛在結果。演算法以深度優先的方式遍歷樹,依序探索每條路徑,直到找到有效解決方案或耗盡所有可能性。

Algorithm

  • Begin with two void sets, SetA and SetB, to address the two subsets being shaped.

  • 遞歸地調查來自給定集合的組件的所有潛在混合,以便記住SetA和SetB中的內容

  • 在每個步驟中,將一個元件新增至SetA並對多餘的元件進行遞歸,或將其新增至SetB並進行遞歸

  • 在遞歸過程中監控SetA和SetB的數量

  • If anytime, the amount of SetA rises to the amount of SetB, bring Valid back; in any case, get back Misleading.

Example

#include <iostream>
#include <vector>

bool isValidSubset(const std::vector<int>& inputSet, int index, int 
setSizeA, int setSizeB) {
   if (index == inputSet.size()) {
      return (setSizeA == setSizeB);
   }

   bool isValid = isValidSubset(inputSet, index + 1, setSizeA + 1, setSizeB);
   isValid |= isValidSubset(inputSet, index + 1, setSizeA, setSizeB + 1);

   return isValid;
}

int main() {
   std::vector<int> inputSet = {1000, 2000, 3000, 4000, 5000};
   bool isValid = isValidSubset(inputSet, 0, 0, 0);
   std::cout << (isValid ? "Valid" : "Misleading") << std::endl;
   return 0;
}

输出

Misleading

结论

本文研究了集合分割问题的NP完备性,该问题包括决定给定的一组正整数是否可以被分割成两个子集,使得它们的和相等。NP完备性意味着没有已知的多项式时间算法可以解决该问题的所有情况,并且验证一个潜在解决方案可以在多项式时间内完成。本文讨论了三种方法来解决这个问题:蛮力法、回溯法和动态规划。由于其复杂性,解决集合分割问题的大规模实例可能需要大量的时间和努力,使得寻找一个理想的解决方案变得具有挑战性。理解集合分割的复杂性很重要,因为它与其他NP完备问题相关,为我们揭示了计算复杂问题的更广泛教训

以上是集合劃分是NP完全的的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:tutorialspoint.com。如有侵權,請聯絡admin@php.cn刪除

相關文章

看更多