[英]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.