当前位置: 首页 > 知识库问答 >
问题:

动态规划:带负数的完全和

姚阳德
2023-03-14
Example: 
Input : arr[] = {1, 2, 3, 4, 5}
        sum = 10
Output : [4 3 2 1]  
         [5 3 2] 
         [5 4 1]

Input : arr[] = {-1, 2, 3, 4, 5}
        sum = 10
Output : [5 3 2] 
         [5 4 2 -1]
import java.util.ArrayList;

// sum problem
class GFG {

    static boolean subset[][];

    // Returns true if there is a subset of
    // set[] with sun equal to given sum
    static boolean isSubsetSum(int set[],
                               int n, int sum) {
        // The value of subset[i][j] will be
        // true if there is a subset of
        // set[0..j-1] with sum equal to i
        subset = new boolean[n + 1][sum + 1];

        // Fill the subset table in botton
        // up manner
        for (int i = 0; i <= n; i++) {
            for (int j = 0; j <= sum; j++) {
                if (j == 0) {
                    subset[i][j] = true;
                } else if (i <= 0 && sum >= 1)
                    subset[i][j] = false;
                else if (set[i - 1] > j)
                    subset[i][j] = subset[i - 1][j];
                else {
                    if (set[i - 1] >= 0)
                        subset[i][j] = subset[i - 1][j] || subset[i - 1][j - set[i - 1]];
                    else
                        subset[i][j] = subset[i - 1][j] || subset[i - 1][j + set[i - 1]];
                }
            }
        }

        // uncomment this code to print table
//        for (int i = 0; i <= sum; i++)
//        {
//        for (int j = 0; j <= n; j++)
//            System.out.println (subset[i][j]);
//        }

        return subset[n][sum];
    }

    /* Driver program to test above function */
    public static void main(String args[]) {
        int set[] = {1, 2, 3, 4, 5};
        int sum = 10;
        int n = set.length;
        if (isSubsetSum(set, n, sum) == true)
            System.out.println("Found a subset"
                    + " with given sum");
        else
            System.out.println("No subset with"
                    + " given sum");
        System.out.println("Done");
        ArrayList<Integer> list = new ArrayList<>();
        printSubsets(set, n, sum, list);
        System.out.println("Finished");
    }

    static void display(ArrayList<Integer> v) {
        System.out.println(v);
    }

    private static void printSubsets(int[] set, int i, int sum, ArrayList<Integer> list) {
        if (i == 0 && sum != 0 && subset[0][sum]) {
            list.add(set[i]);
            display(list);
            list.clear();
            return;
        }

        // If sum becomes 0
        if (i == 0 && sum == 0) {
            display(list);
            list.clear();
            return;
        }

        // If given sum can be achieved after ignoring
        // current element.
        if (subset[i - 1][sum]) {
            // Create a new vector to store path
            ArrayList<Integer> b = new ArrayList<>();
            b.addAll(list);
            printSubsets(set, i - 1, sum, b);
        }

        // If given sum can be achieved after considering
        // current element.

        if (sum >= set[i - 1] && subset[i - 1][sum - set[i - 1]]) {
            list.add(set[i - 1]);
            printSubsets(set, i - 1, sum - set[i - 1], list);
        }

    }   
} 

共有1个答案

越勇
2023-03-14

由于您必须打印(或生成)给定集合的所有可能的子集(包含正整数和负整数),这些子集的总和等于sum,所以您可以做的是:

尝试将set的每个位置表示为0和1的二进制表示,其中1表示取那个位置的元素,0表示不考虑那个位置的元素。

求有1的所有位置的总和。如果这些值的总和恰好等于给定的总和,则打印该子集。

import java.util.Arrays;

public class PerfectSum {

public static void printSubsets(int[] set, int n, int sum) {
     int totalSubSets = (1 << n);
     for (int i = 1; i < totalSubSets; ++i) { // loop over all possible subsets
         int curSum = 0;
         for (int j = n - 1; j >= 0; --j) {
             if (((i >> j) & 1) > 0) { // if bit at jth position is 1 take that value
                curSum +=set[j];
             }
         }
         if (curSum == sum) { // valid subset found, then print it
             for (int j = n - 1; j >= 0; --j) { // looping in reverse order to print set in decreasing order
                 if (((i >> j) & 1) > 0) { // if bit at jth position is 1 take that value
                     System.out.print(set[j] + " ");
                 }
             }
             System.out.println("");
         }
     }
}

public static void main(String[] args) {
    int set[] = {-1, 2, 3, 4, 5};
    Arrays.sort(set); // To print in non increasing order
    int sum = 10;
    int n = set.length;
    printSubsets(set, n, sum);
  }
}
 类似资料:
  • 计算机科学中的许多程序是为了优化一些值而编写的; 例如,找到两个点之间的最短路径,找到最适合一组点的线,或找到满足某些标准的最小对象集。计算机科学家使用许多策略来解决这些问题。本书的目标之一是向你展示几种不同的解决问题的策略。动态规划 是这些类型的优化问题的一个策略。 优化问题的典型例子包括使用最少的硬币找零。假设你是一个自动售货机制造商的程序员。你的公司希望通过给每个交易最少硬币来简化工作。假设

  • *正则匹配问题[H] 三角形问题[M] 计算二进制数中1的个数[M] *括号匹配问题[M] 最短路径和[M]

  • 本文向大家介绍动态规划和带记忆递归的区别相关面试题,主要包含被问及动态规划和带记忆递归的区别时的应答技巧和注意事项,需要的朋友参考一下 参考回答: 自顶而下和自底而上

  • 主要内容:动态规划算法的实际应用动态规划算法解决问题的过程和分治算法类似,也是先将问题拆分成多个简单的小问题,通过逐一解决这些小问题找到整个问题的答案。不同之处在于,分治算法拆分出的小问题之间是相互独立的,而动态规划算法拆分出的小问题之间相互关联,例如要想解决问题 A,必须先解决问题 B 和 C。 《贪心算法》一节中,给大家举过一个例子,假设有 1、7、10 这 3 种面值的纸币,每种纸币使用的数量不限,要求用尽可能少的纸币拼凑

  • 我正在尝试实施这个问题的解决方案,但我遇到了一些问题。 问题是: “在r行和c列的网格的左上角有一个机器人。机器人只能向右或向下移动,某些单元格是“禁止”的,这意味着机器人不能踩它们。设计一个算法来为机器人找到从左上角到右下的路径。” 解决方案如下所示: 让我困惑的是动态编程的尝试。 从不计算为。 我已经覆盖了Point类中的和方法,所以失败了。只要所比较的对象具有相同的行和列值,contains

  • 我有一个子集问题的工作代码,如果它发现一个子集等于所需的目标,它可以打印数字。 > 我想打印给定目标的所有可能的子集,我不知道要为此更改什么。 我如何让它对负数起作用?