Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/eclipse/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 子集和算法_Algorithm_Dynamic Programming_Subset Sum - Fatal编程技术网

Algorithm 子集和算法

Algorithm 子集和算法,algorithm,dynamic-programming,subset-sum,Algorithm,Dynamic Programming,Subset Sum,我正在研究这个问题: 子集和问题以一组X={x1,x2,…,xn}整数和另一个K整数作为输入。问题是检查是否存在X的子集X',其元素总和为K,如果存在,则查找子集。例如,如果X={5,3,11,8,2}和K=16那么答案是YES,因为子集X'={5,11}的和为16。实现运行时间至少为O(nK)的子集和算法 注意复杂性O(nK)。我认为动态规划可能会有所帮助 我发现了一个指数时间算法,但它没有帮助 有人能帮我解决这个问题吗?在一般情况下,对于运行时间小于O(2^(n/2))的子集和,没有已知的算

我正在研究这个问题:

子集和问题以一组
X={x1,x2,…,xn}
整数和另一个
K
整数作为输入。问题是检查是否存在
X
的子集
X'
,其元素总和为
K
,如果存在,则查找子集。例如,如果
X={5,3,11,8,2}
K=16
那么答案是
YES
,因为子集
X'={5,11}
的和为
16
。实现运行时间至少为
O(nK)
的子集和算法

注意复杂性
O(nK)
。我认为动态规划可能会有所帮助

我发现了一个指数时间算法,但它没有帮助


有人能帮我解决这个问题吗?

在一般情况下,对于运行时间小于O(2^(n/2))的子集和,没有已知的算法。

因为看起来所有的数字都是正数,所以可以使用动态规划来解决这个问题:

启动一个大小为K+1的布尔数组
可能
,第一个值为true,其余值为false。第i个值将表示是否可以实现i的子集和。对于集合中的每个数字n,循环遍历
可能的
数组,如果第i个值为真,则将第i+n个值也设置为真

最后,如果
可能
中的第k个值为真,则可以形成k的子集和。问题在O(NK)时间内解决

对应用于不保证为正的整数集的该算法进行了详细解释。

我建议阅读的算法。算法存在于那里,请参见伪多项式时间动态规划解对于
O(P*n)
解,解不是多项式时间,是(P,n)中的多项式,但它不是n+log P(输入大小)中的多项式,因为
P
可以非常大,如2^n,解P*n=(2^n)*一般来说,n不是多项式时间解,但当p有某个多项式函数的界时,n是多项式时间算法

这个问题是NPC,但它有一个
伪多项式时间
算法,属于问题,也有问题,这意味着,除非p=NP,否则你找不到任何
伪多项式时间
算法,而这个问题不在这一问题范围内,所以从某种程度上说很容易

我说的尽可能简单,但这不是强NP完全或弱NP完全问题的精确定义

有关详细信息,请参见第4章。

无效子项(int arr[],int size,int target){
void subsetSum (int arr[], int size, int target) {
  int i, j ;
  int **table ;
  table = (int **) malloc (sizeof(int*) * (size+1)) ;
  for ( i = 0 ; i <= size ; i ++ ) {
    table[i] = (int *) malloc (sizeof(int) * (target+1)) ;
    table[i][0] = 1 ;
  }
  for ( j = 1 ; j <= target ; j ++ )
    table[0][j] = 0 ;
  for ( i = 1 ; i <= size ; i ++ ) {
    for ( j = 1 ; j <= target ; j ++ )
      table[i][j] = table[i-1][j] || (arr[i-1] <= j && table[i-1][j-arr[i-1]] ) ;
  } 
  if ( table[size][target] == 1 )
    printf ( "\ntarget sum found\n" ) ; 
  else printf ( "\nTarget sum do not found!\n" ) ;
  free (table) ;
}
int i,j; int**表格; 表=(int**)malloc(sizeof(int*)*(size+1));
对于(i=0;iDP)一维数组解决方案(这里DP数组处理顺序很重要)

bool subsetsum\u dp(向量和向量,整数和)
{
int n=v.size();
常量int MAX_元素=100;
常量int最大元素值=1000;
静态int-dp[MAX_-ELEMENT*MAX_-ELEMENT_-VALUE+1];memset(dp,0,sizeof(dp));
dp[0]=1;
对于(int i=0;i=0;j--)
{
如果(j-v[i]<0)继续;
如果(dp[j-v[i]])dp[j]=1;
}
}
返回dp[总和]?真:假;
}

设M为所有元素之和。 注意K
布尔hasSubset(int arr[],int remSum,int lastElem){
if(remSum==0)返回true;
else if(remSum!=0&&lastelemsum)返回hasSubset(arr、remSum、lastElem-1);
否则返回(hasSubset(arr,remSum,lastElem-1)| | hasSubset(arr,remSum,arr[lastElem],lastElem-1));
}

考虑第i个元素。它将对子集和起作用或不起作用。如果它对和起作用,则“和值”将减少等于第i个元素的值。如果它不起作用,则我们需要搜索“和值”在剩下的元素中。

子集和是我在Macalester学习的第一个NP完全问题。这个问题被浏览了36000多次,但我没有看到足够的答案来详细解释算法的逻辑。所以我想我尝试这样做

假设:

为了简单起见,首先我假设输入集
X
只包含正整数,并且
k
为正。但是,我们可以调整算法来处理负整数,如果
k
为负

逻辑:

该算法或任何DP问题的关键在于分解问题,从基本情况开始。
然后我们可以利用我们知道的一些知识在基本情况基础上进行构建:

  • 我们知道,如果集合
    X
    为空,则无法求和
    k
    的任何值
  • 如果集合
    X
    包含
    k
    ,则它有一个子集和
    k
  • 我们知道,如果集合
    x1
    的子集是
    X
    的子集,那么
    X
    将有一个子集和
    k1
    ,即
    x1
  • 我们有一个集合
    X={x1,x1,x3,…,xn,xn+1}
    。我们知道它有一个子集和
    k1
    ,如果
    x1={x1,x1,x3,…,xn}
    有一个子集和
    k-k1
  • 举例说明1,2,3,4:

  • 这很简单。如果你有一个空集{},你就不能有这样的子集 不能有任何子集和
  • 集合
    X={4}
    的子集和为4,因为它本身就是集合的一部分

  • 假设你有一个集合
    x1={1,3,5}
    ,它是集合
    X={1,3,5,2,8}
    的子集。如果
    x1
    的子集和为
    k1=8
    ,那意味着
    X
    也有一个子集和为8,因为
    x1
    X
    的子集

  • 假设你有一套
    bool subsetsum_dp(vector<int>& v, int sum)
    {
        int n = v.size();
        const int MAX_ELEMENT = 100;
        const int MAX_ELEMENT_VALUE = 1000;
        static int dp[MAX_ELEMENT*MAX_ELEMENT_VALUE + 1]; memset(dp, 0, sizeof(dp));
    
        dp[0] = 1;
    
        for (int i = 0; i < n; i++)
        {
            for (int j = MAX_ELEMENT*MAX_ELEMENT_VALUE; j >= 0; j--)
            {
                if (j - v[i] < 0) continue;
                if (dp[j - v[i]]) dp[j] = 1; 
            }
        }
    
        return dp[sum] ? true : false;
    }
    
    let m be a Boolean array [0...M]
    set all elements of m to be False
    m[0]=1
    for all numbers in the set let a[i] be the ith number
        for j = M to a[i]
            m[j] = m[j] | m[j-a[i]];
    
    boolean hasSubset(int arr[],int remSum,int lastElem){
        if(remSum==0) return true;
        else if(remSum!=0 && lastElem<0) return false;
    
        if(arr[lastElem]>remSum) return hasSubset(arr, remSum, lastElem-1);
        else return (hasSubset(arr, remSum, lastElem-1) ||hasSubset(arr, remSum-arr[lastElem], lastElem-1));
    }
    
    X = {1,3,5,2,8}
    k = 9
    
       0 1 2 3 4 5 6 7 8 9
       _ _ _ _ _ _ _ _ _ _
    0| F F F F F F F F F F
    1|
    2|
    3|
    4|
    5|
    
       0 1 2 3 4 5 6 7 8 9
       _ _ _ _ _ _ _ _ _ _
    0| F F F F F F F F F F
    1| F T F F F F F F F F
    2| F T F T T F F F F F 
    3| F T F T T T T F T T
    4| F T T T T T T T T T 
    5| F T T T T T T T T T
    
    import java.util.*;
    
    public class SubSetSum {
    
        public static boolean subSetSum(int[] a, int k){
    
            if(a == null){
                return false;
            }
    
            //n items in the list
            int n = a.length; 
            //create matrix m
            boolean[][] m = new boolean[n + 1][k + 1]; //n + 1 to include 0, k + 1 to include 0 
    
            //set first row of matrix to false. This also prevent array index out of bounds: -1
            for(int s = 0; s <= k; s++){
                m[0][s] = false;
            }
    
            //populate matrix m
            for(int i = 1; i <= n; i++){
                for(int s = 0; s <= k; s++){    
                    if(s - a[i-1] >= 0){ //when it goes left we don't want it to go out of bounds. (logic 4)
                        m[i][s] = (m[i-1][s] || a[i-1] == s || m[i-1][s - a[i-1]]); 
                    } else {
                        m[i][s] = (m[i-1][s] || a[i-1] == s);
                    }       
    
                }
            }
    
            //print matrix
            print(m);
    
            return m[n][k];
    
        }
    
        private static void print(boolean[][] m){
            for(int i = 0; i < m.length; i++){
                for(int j = 0; j < m[i].length; j++){
                    if(m[i][j]){
                        System.out.print("T");
                    } else {
                        System.out.print("F");
                    }           
                }
                System.out.print("\n");
            }
        }
    
        public static void main(String[] args){
            int[] array = {1,3,5,2,8};
            int k = 9;
    
            System.out.println(subSetSum(array,k));
    
        }
    }
    
    ┌─────────┬──────┬──────┬──────┬──────┬──────┬──────┬──────┬──────┬──────┬──────┬──────┬──────┐
    │ (index) │  0   │  2   │  3   │  5   │  7   │  8   │  10  │  11  │  13  │  14  │  15  │  16  │
    ├─────────┼──────┼──────┼──────┼──────┼──────┼──────┼──────┼──────┼──────┼──────┼──────┼──────┤
    │    0    │ true │      │      │      │      │      │      │      │      │      │      │      │
    │    5    │ true │      │      │ true │      │      │      │      │      │      │      │      │
    │    3    │ true │      │ true │ true │      │ true │      │      │      │      │      │      │
    │    11   │ true │      │ true │ true │      │ true │      │ true │      │ true │      │ true │
    │    8    │ true │      │ true │ true │      │ true │      │ true │ true │ true │      │ true │
    │    2    │ true │ true │ true │ true │ true │ true │ true │ true │ true │ true │ true │ true │
    └─────────┴──────┴──────┴──────┴──────┴──────┴──────┴──────┴──────┴──────┴──────┴──────┴──────┘
    
    public class SubSetSum {
        boolean[][] solution; 
        int[] input;
        int k;
    
        public SubSetSum(int[] input, int targetSum) {
            this.input = input;
            this.k = targetSum;
            this.solution = new boolean[input.length+1][k+1];
        }
    
        public boolean subsetSum() {
            int n = input.length;
    
            for (int i = 0; i <= n; i++) {     //case 1
                solution[i][0] = true;
            }
    
            for (int j = 0; j <= k; j++) {    // case 2
                solution[0][j] = false;
            }
    
            for (int i = 1; i <= n; i++) {                  // n times
                for (int j = 1; j <= k; j++) {              // k times and time complexity O(n*k)
                    if(solution[i-1][j]) {
                        solution[i][j] = solution[i-1][j];      // case 3
                        continue;
                    }
                    if(j >= input[i-1])  {                       // case 4
                        solution[i][j] = solution[i-1][j-input[i-1]];
                    }
                }
            }
            return solution[n][k];
        }
    }
    
    function subsetsum(a, n) {
        var r = [];
        for (var i = parseInt(a.map(function() { return 1 }).join(''), 2); i; i--) {
            var b = i.toString(2).split('').reverse().map(function(v, i) {
                return Number(v) * a[i]
            }).filter(Boolean);
            if (eval(b.join('+')) == n) r.push(b);
        }
        return r;
    }
    
    var a = [5, 3, 11, 8, 2];
    var n = 16;
    console.log(subsetsum(a, n)); // -> [[3, 11, 2], [5, 3, 8], [5, 11]]
    
    public void solveSubsetSum(){
        int set[] = {2,6,6,4,5};
                int sum = 9;
                int n = set.length;
    
                // check for each element if it is a part of subset whose sum is equal to given sum
                for (int i=0; i<n;i++){
                    if (isSubsetSum(set, sum, i, n)){
                        Log.d("isSubset:", "true") ;
                        break;
                    }
                    else{
                        Log.d("isSubset:", "false") ;
                    }
                    k=0; // to print time complexity pattern
                }
            }
    
    private boolean isSubsetSum(int[] set, int sum, int i, int n) {
    
                for (int l=0;l<k; l++){
                System.out.print("*"); 
                // to print no of time is subset call for each element
            }
            k++;
            System.out.println();     
            if (sum == 0){
                return true;
            }
    
            if (i>=n){
                return false;
            }
    
            if (set[i] <= sum){ 
            // current element is less than required sum then we have to check if rest of the elements make a subset such that its sum is equal to the left sum(sum-current element)
                return isSubsetSum(set, sum-set[i], ++i, n);
            }
            else { //if current element is greater than required sum
                return isSubsetSum(set, sum, ++i, n);
            }
       }