首頁 Java java教程 子集和問題的實例詳解

子集和問題的實例詳解

Jul 03, 2017 am 11:03 AM
動態規劃 子集 問題

註:因為「子集與問題」的學習不夠深入,所以本文在講解動態規劃遞推公式中可能存在敘述不清,或者錯誤的地方,如有發現望能不吝賜教。

  子集與問題可描述如下:給定n個正整數W=(w #1, w2, …, wn)與正整數M,要求尋找這樣一個子集I⊆{1, 2, 3, ..., n},使得∑wi=M,i∈I[1] 。舉個例子對子集和問題做一個通俗的解釋:集合W=(1, 2, 3, 4, 5),給定一個正整數#M =5,是否存在W#的子集#,使得子集 #I中的元素相加等於M,這個例子顯然存在子集I=(2, 3)。

  問題定義:正整數集合S=(w1, w2, w3, …wn),給定正整數Ws[i, j]中的##i表示S的子集,j表示子集i的和。如果S的某個集合i元素之和j=M##,即問題有解。   舉例:

S=(7, 34, 4, 12, 5, 3)

W=6 #,是否存在S的子集,它的元素總和等於W  這個問題同樣有多種解法,在本文中利用動態規劃的想法來求解,那麼就需要推導出一個遞推公式。我們將集合

S

不斷的分割成小的集合,這就是動態規劃的第一步:定義子問題。集合S最小的集合就是空集合,空集合當然不存在它的元素總和等於W,當然若j=0的情況下空集合是符合條件的。

  這個表格的欄位代表的是集合中的元素總和,最多只到達元素W,大於##W當然沒意義了。只要在j=6列中出現1,即得到問題的解。行表示前i個(包括i)元素組成的子集(這句話可能會有點疑問,這樣豈不是掃描不到所有情況嗎? i=0表示為空集合。

  我們定義了

j=6時,空集合情況為true#。那麼當j=0時,這樣對任意子集和都成立(空集合是它們的子集)。所以表格繼續填入如下圖。

  這些其實是

動態規劃的第三步:定義初始狀態。狀態規劃第二步則是定義狀態轉移規則,即狀態之間的遞推關係。

  s[i, j]

中的i表示的是前i


個子集(包括i)。實際上我們從這裡進行劃分為兩部分:    1)不包括第i個元素的前#i個子集,即

###s[i - 1, j]#######;#########    2)包含第###i#######個元素的前######i######個子集。 ######  對於第###1)######種情況較易理解,前######i - 1######個集合元素總和等於### ###j######,那麼前######i######個集合元素就存在子集元素總和等於######j#######。 ######

  難於理解的是第2)種情況。對於第二種情況能明確一點就是s[i, X]中的i是確定的,關鍵是jj此時如何定義?利用數學中的特值法#,舉例集合(3, 34, 9),是否存在給定子集的元素總和等於37##i=2(子集為(3, 34)),j = 37,此時 #包括第i個元素的前i子集這種情況下,s[2, 37] => s[2, 37 - 34] = s[2, 3],子集(3 , 34)當然存在它的子集元素總和等於3。那如果j = 36s[2, 36] => s[2, 36 - 34] = s[2, 2],子集(3, 34)顯然不存在它的子集元素總和等於2。那j = 1呢,

s[2, 1] => s[2, 1 - 34] = s[2, -32]

j - wi < 0

#,此時

s[2, 1] => s[2 - 1, 1] = s[1, 1],子集(3)顯然不存在它的子集元素總和等於1  綜上,遞推式如下圖:  在用程式碼實作這個演算法前,先透過遞推公式填入上面的矩陣。   ①i = 1, 此時子集為(7)

j = 1#######, ######j ###∉ (∅)###,選擇狀況######2) => s[0, 1] || s[1, -6]#### ##(######i = 0######表示空集合)。顯然######s[1, 1] = 0######。 ######

  ②i = 1此时子集为(7)j = 2j ∉ (∅),选择情况2) => s[0, 2] || s[1, -5]i = 0表示空集)。显然s[1, 2] = 0

  ……

  ⑥i = 1,此时子集为(7)j = 6,∉ (∅),选择情况2) => s[0, 6] || s[1, -1]i = 0表示空集)。显然s[1, 6] = 0

  最后填充为如下图所示:

  继续填充最后一行:  

  ①i = 6, 此时子集为(7, 34, 4, 12, 5, 3)j = 1∉ (7, 34, 4, 12, 5),选择情况2) => s[5, 1] || s[6, -2]i = 0表示空集)。显然s[6, 1] = 0

  ②i = 6, 此时子集为(7, 34, 4, 12, 5, 3)j = 2,∉ (7, 34, 4, 12, 5),选择情况2) => s[5, 1] || s[6, -1]i = 0表示空集)。显然s[6, 2] = 0

  ③i = 6, 此时子集为(7, 34, 4, 12, 5, 3)j = 3,∉ (7, 34, 4, 12, 5),选择情况2) => s[5, 1] || s[6, 0]。显然s[6, 3] = 1

  ...

  ⑥i = 6, 此时子集为(7, 34, 4, 12, 5, 3), j = 6, j ∉ (7, 34, 4, 12, 5),选择情况2) => s[5, 6] || s[6, 3]。显然s[6, 6] = 1

  Java

 1 package com.algorithm.dynamicprogramming; 2  3 import java.util.Arrays; 4  5 /** 6  * 子集和问题 7  * Created by yulinfeng on 7/2/17. 8  */ 9 public class SubsetSumProblem {10 11     public static void main(String[] srgs) {12         int[] sets = {7, 34, 4, 12, 5, 3};13         int sum = 87;14         boolean isExistSubSet = subsetSumProblem(sets, sum);15         System.out.println("集合" + Arrays.toString(sets) + "是否存在子集的和等于" + sum + ":" + isExistSubSet);16     }17 18     private static boolean subsetSumProblem(int[] sets, int sum) {19         int row = sets.length + 1;20         int col = sum + 1;21         int[][] solutionMatrix = new int[row][col];22         solutionMatrix[0][0] = 1;23 24         /**25          *    0 1 2 3 4 5 626          * 0 |1|0|0|0|0|0|0|27          * 1 |x|x|x|x|x|x|x|28          * 2 |x|x|x|x|x|x|x|29          * 3 |x|x|x|x|x|x|x|30          * 3 |x|x|x|x|x|x|x|31          * 4 |x|x|x|x|x|x|x|32          * 5 |x|x|x|x|x|x|x|33          * 6 |x|x|x|x|x|x|x|34          */35         for (int i = 1; i < col; i++) {36             solutionMatrix[0][i] = 0;37         }38         /**39          * 初始状态40          *    0 1 2 3 4 5 641          * 0 |1|0|0|0|0|0|0|42          * 1 |1|0|x|x|x|x|x|43          * 2 |x|x|x|x|x|x|x|44          * 3 |x|x|x|x|x|x|x|45          * 3 |x|x|x|x|x|x|x|46          * 4 |x|x|x|x|x|x|x|47          * 5 |x|x|x|x|x|x|x|48          * 6 |1|0|0|x|x|x|x|49          * [i][0] = 1,按行填充50          */51         for (int i = 1; i < row; i++) {52             solutionMatrix[i][0] = 1;53             for (int j = 1; j < col; j++) {54                 solutionMatrix[i][j] = solutionMatrix[i - 1][j];55 56                 if (solutionMatrix[i][j] == 1) {57                     solutionMatrix[i][j] = solutionMatrix[i][j];58                 } else if ( j - sets[i - 1] >= 0 && solutionMatrix[i][j - sets[i - 1]] == 1) {59                     solutionMatrix[i][j] = solutionMatrix[i][j - sets[i - 1]];60                 } else {61                     solutionMatrix[i][j] = 0;62                 }63 64                 if (j == col - 1 && solutionMatrix[i][j] == 1) {65                     return true;66                 }67             }68         }69 70         return false;71     }72 }
登入後複製

  Python3

 1 def subset_sum_problem(sets, sum): 2     row = len(sets) + 1 3     col = sum + 1 4     solutionMatrix = [[0 for col in range(col)] for row in range(row)] 5     solutionMatrix[0][0] = 1 6     for i in range(1, col): 7         solutionMatrix[0][i] = 0 8  9     for j in range(1, row):10         solutionMatrix[j][0] = 111         for k in range(1, col):12             solutionMatrix[j][k] = solutionMatrix[j - 1][k]13             if solutionMatrix[j][k] == 1:14                 solutionMatrix[j][k] = solutionMatrix[j][k]15             elif (k - sets[j - 1] >= 0) and (solutionMatrix[j][k - sets[j - 1]] == 1):16                 solutionMatrix[j][k] = solutionMatrix[j][k - sets[j - 1]]17             else:18                 solutionMatrix[j][k] = 019             if k == col - 1 and solutionMatrix[j][k] == 1:20                 return True21 22     return False23 24 sets = [7, 34, 4, 12, 5, 3]25 num = 626 is_exist = subset_sum_problem(sets, num)27 print(is_exist)
登入後複製


以上是子集和問題的實例詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

聚類演算法中的聚類效果評估問題 聚類演算法中的聚類效果評估問題 Oct 10, 2023 pm 01:12 PM

聚類演算法中的聚類效果評估問題,需要具體程式碼範例聚類是一種無監督學習方法,透過對資料進行聚類,將相似的樣本歸為一類。在聚類演算法中,如何評估聚類的效果是一個重要的問題。本文將介紹幾種常用的聚類效果評估指標,並給出對應的程式碼範例。一、聚類效果評估指標輪廓係數(SilhouetteCoefficient)輪廓係數是透過計算樣本的緊密度和與其他簇的分離度來評估聚類效

解決C++程式碼中出現的「error: redefinition of class 'ClassName'」問題 解決C++程式碼中出現的「error: redefinition of class 'ClassName'」問題 Aug 25, 2023 pm 06:01 PM

解決C++程式碼中出現的「error:redefinitionofclass'ClassName'」問題在C++程式設計中,我們常常會遇到各種各樣的編譯錯誤。其中一個常見的錯誤是「error:redefinitionofclass'ClassName'」(類別『ClassName』的重定義錯誤)。這個錯誤通常出現在同一個類別被定義了多次的情況下。本文將

教你如何診斷常見問題的iPhone故障 教你如何診斷常見問題的iPhone故障 Dec 03, 2023 am 08:15 AM

iPhone以其強大的性能和多方面的功能而聞名,它不能倖免於偶爾的打嗝或技術困難,這是複雜電子設備的共同特徵。遇到iPhone問題可能會讓人感到沮喪,但通常不需要警報。在這份綜合指南中,我們旨在揭開與iPhone使用相關的一些最常遇到的挑戰的神秘面紗。我們的逐步方法旨在幫助您解決這些常見問題,提供實用的解決方案和故障排除技巧,讓您的裝置恢復到最佳工作狀態。無論您是面對一個小故障還是更複雜的問題,本文都可以幫助您有效地解決這些問題。一般故障排除提示在深入研究具體的故障排除步驟之前,以下是一些有助於

PHP演算法解析:如何使用動態規劃演算法解決最長回文子字串問題? PHP演算法解析:如何使用動態規劃演算法解決最長回文子字串問題? Sep 19, 2023 pm 12:19 PM

PHP演算法解析:如何使用動態規劃演算法解決最長回文子字串問題?動態規劃(DynamicProgramming)是一種常用的演算法思想,可以解決許多複雜的問題。其中之一是最長回文子字串問題,即求字串中最長的回文子字串的長度。本文將介紹如何使用PHP編寫動態規劃演算法來解決這個問題,並提供具體的程式碼範例。先來定義一下最長回文子字串。回文字串是指正反讀都一樣的字串,而回

如何使用C#撰寫動態規劃演算法 如何使用C#撰寫動態規劃演算法 Sep 20, 2023 pm 04:03 PM

如何使用C#撰寫動態規劃演算法摘要:動態規劃是求解最最佳化問題的常用演算法,適用於多種場景。本文將介紹如何使用C#編寫動態規劃演算法,並提供具體的程式碼範例。一、什麼是動態規劃演算法動態規劃(DynamicProgramming,簡稱DP)是一種用來求解具有重疊子問題和最優子結構性質的問題的演算法想法。動態規劃將問題分解成若干個子問題來求解,透過記錄每個子問題的解,

解決jQuery無法取得表單元素值的方法 解決jQuery無法取得表單元素值的方法 Feb 19, 2024 pm 02:01 PM

解決jQuery.val()無法使用的問題,需要具體程式碼範例對於前端開發者,使用jQuery是常見的操作之一。其中,使用.val()方法來取得或設定表單元素的值是非常常見的操作。然而,在一些特定的情況下,可能會出現無法使用.val()方法的問題。本文將介紹一些常見的情況以及解決方案,並提供具體的程式碼範例。問題描述在使用jQuery開發前端頁面時,有時候會碰

弱監督學習中的標籤獲取問題 弱監督學習中的標籤獲取問題 Oct 08, 2023 am 09:18 AM

弱監督學習中的標籤獲取問題,需要具體程式碼範例引言:弱監督學習是一種利用弱標籤進行訓練的機器學習方法。與傳統的監督學習不同,弱監督學習只需利用較少的標籤來訓練模型,而不是每個樣本都需要有準確的標籤。然而,在弱監督學習中,如何從弱標籤中準確地獲取有用的信息是一個關鍵問題。本文將介紹弱監督學習中的標籤獲取問題,並給出具體的程式碼範例。弱監督學習中的標籤獲取問題簡介:

如何使用C++中的背包問題演算法 如何使用C++中的背包問題演算法 Sep 21, 2023 pm 02:18 PM

如何使用C++中的背包問題演算法背包問題是電腦演算法中經典的問題之一,它涉及在給定的背包容量下,如何選擇一些物品放入背包,使得物品的總價值最大化。本文將詳細介紹如何使用C++中的動態規劃演算法來解決背包問題,並給出具體的程式碼範例。首先,我們需要定義背包問題的輸入和輸出。輸入包括物品的重量數組wt[],物品的價值數組val[],以及背包的容量W。輸出為選擇哪些物

See all articles