我对子集求和问题有困难。
首先,我试图找到匹配目标的子集总和。第一个原始集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
答案 0 :(得分:0)
您的算法是扫描列表,包括值,只要它们不会给您太大的金额。这是一个贪婪的&#34;算法,因为它假定看起来可能有效的东西,会起作用。但是你有一个存在的证据表明这种问题并不适用(在这种情况下,一旦你加入了2,你就会失败)。
正如您在描述中所说:有很多可能的组合,您的程序需要检查更多。例如,对于列表中的每个值,您可以尝试使用包含的那些元素构建列表中其余元素的子集,然后尝试不包含它的那些元素。这将允许您检查所有可能的子集。
答案 1 :(得分:0)
您的方法findSubset(int target)
不正确。此方法实际上将值sum
初始化为零,然后循环遍历subset
中的每个元素,并将其添加到解决方案子集中,如果其值加sum
小于或等于{{1} }}。此算法不考虑target
中的所有子集(它实际上不会考虑subset
的任何子集,只考虑整个subset
。)。此外,此算法将返回subset
中具有等于或小于 subset
的累积和的元素。
解决此问题的明显方法是生成target
的每个可能子集,然后遍历每个子集,对元素求和,并在总和等于subset
时返回该子集。通过记忆子集和,可以使用动态编程来改进这种方法。
顺便说一下,您可能希望将设置结构命名为target
而不是set
,以避免混淆。 :)
希望这有帮助!