簡體   English   中英

Java子集總和的難度

[英]Difficulty with subset sum java

我在子集總和問題上遇到了困難。

首先,我試圖找到子集的總和以匹配我的目標。 第一原始集合S是[3,4,6,2,15,7,5,1,11] 我從文件中讀取並將價格存儲在ArrayList 然后,我讓用戶輸入一個數量,然后對子集求和以匹配用戶輸入的數量,或者給出與輸入的數量匹配或接近的近似子集總和。

輸入25時算法錯誤。 它給出[3,4,6,2,7,1] ,這是錯誤的。 目標量25具有幾種解決方案,分別是[4,6,15], [15,7,3], [3,4,6,7,5], [3,4,6,11,1], [3,2,15,5].

我正在嘗試找到總計為2的子集,並在可能的情況下獲得最佳解決方案。 在我的原始列表中,由於有9個元素,因此有512個子集組合。 我很難在代碼中實現這一點。

碼:

class Subset{
    private ArrayList<Integer> subset;
    private Scanner scan;

    public Subset(String filename) {
        try {
            File file = new File(filename);
            Scanner scan = new Scanner(file);
            subset = new ArrayList<Integer>();

            while(scan.hasNext()) {
                String readLine = scan.nextLine();
                int num = Integer.parseInt(readLine.split(" ")[1]);
                subset.add(num);
            }
        } catch(FileNotFoundException ex) {
            System.out.println(ex.getMessage());
        } finally {
            scan.close();
        }
    }

    public ArrayList<Integer> getPrices() {
        return this.subset;
    }

    public ArrayList<Integer> findSubset(int target) {
        ArrayList<Integer> newList = new ArrayList<Integer>();
        int sum = 0;
        for (int i = 0; i < subset.size(); i++) {
            if (sum += subset.get(i) <= target) {
                newList.add(subset.get(i));
                sum += newList.get(i);
            }
        }
        return newList;
   }

   public static void main(String[] args) {
       final String FILENAME = "groceries.txt";
       Subset sub = new Subset(FILENAME);
       Scanner scan = new Scanner(System.in);

       ArrayList<Integer> price = sub.getPrices();
       System.out.println("Prices in the list: ");
       System.out.println(price);

       System.out.price("Enter an amount to give you a subset.. ");
       System.out.println("Enter price: ");
       int amount = scan.nextInt();

       ArrayList<Integer> list = sub.findSubset(amount);

       System.out.println("The subset list is: "+list);

       scan.close();
   }
}

我的groceries.txt文件是:

bread 3
garlic 4
coke 6
potato 2
candy 15
chicken 7 
banana 5
tomato 1
beef 11

您的算法是掃描列表,包括值,只要它們不會給您太大的總和。 這是一種“貪婪”算法,因為它假定某些看起來像它可能起作用的東西將起作用。 但是您有一個存在證明,它不適用於這種問題(在這種情況下,一旦包含了2,就會迷路了)。

正如您在描述中所說的那樣:有很多可能的組合,並且您的程序需要檢查更多的組合。 例如,對於列表中的每個值,您可以嘗試構建包含列表中其余元素的子集,然后嘗試不包含該元素的子集。 這樣您就可以檢查所有可能的子集。

您的方法findSubset(int target)不正確。 此方法實質上將值sum初始化為零,然后遍歷subset每個元素,如果其值sum小於或等於target則將其添加到解決方案子集中。 該算法不考慮子subset所有子subset (實際上不考慮子集中的subset ,僅考慮整個subset )。 此外,此算法將返回subset的累積總和等於或小於 target元素。

解決此問題的明顯方法是生成子集的每個可能子subset ,然后遍歷每個子集,對元素求和,如果總和等於target ,則返回該子集。 可以使用動態編程通過記憶子集和來改進此方法。

順便說一句,您可能希望將集合結構命名為set而不是subset以避免混淆。 :)

希望這可以幫助!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM