我对搜索算法和回溯编程很感兴趣。目前,我已经实现了算法 X(请参阅我的另一篇文章:确定无冲突集?)来解决精确覆盖问题。这很好用,但我现在有兴趣使用更基本的回溯变体来解决这个问题。我只是无法弄清楚如何做到这一点。问题描述和之前一样:
假设您有一堆集合,而每个集合都有几个子集。
Set1 = {(香蕉、菠萝、橙子)、(苹果、羽衣甘蓝、黄瓜)、(洋葱、大蒜)}
Set2 = {(香蕉、黄瓜、大蒜)、(鳄梨、番茄)}
...
SetN = { ... }
现在的目标是从每个集合中选择一个子集,而每个子集必须与任何其他选定的子集无冲突(一个元素不包含在任何其他选定的子集中)。
例如,我编写了两个 Java 类。集合由单个字符标识,元素是纯数字。
我具体有两个问题:
- 如何以可以使用启发式的方式迭代所有集/子集(选择具有最少元素、最小成本的子集......)
- 如何维护选定的集合+子集及其包含的元素。
我能找到的所有其他示例都是数独或 n-Queens,并且都使用固定的 for 循环。除此之外,我正在考虑一种相当通用的方法,其中可以使用函数“isPossiblePartialSolution”来检查所选路径/集是否可能与先前选择的子集/元素冲突。
下面是两个 Java 类:
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
ArrayList<Set> allSets = buildRandomTest();
for(Set r : allSets) {
System.out.print("Set with id: " + r.id + " is subset in collection: " + r.name + " and contains: ");
for(Integer n : r.listOfElements) {
System.out.print(" " + n + " ");
}
System.out.println();
}
}
public static int myRandomRange(int low, int high) {
return (int) (Math.random() * (++high - low) + low);
}
public static ArrayList<Set> buildRandomTest() {
ArrayList<Set> mySet = new ArrayList<Set>();
int numberOfSets = myRandomRange(10, 12);
for(int i=0; i<numberOfSets; i++) {
String nameOfSet = Character.toString((char) myRandomRange(65, 67));
Set tmp = new Set(nameOfSet, i);
ArrayList<Integer> listOfElements = new ArrayList<Integer>();
int elementsInList = myRandomRange(2, 4);
for(int j=0; j<elementsInList; j++) {
listOfElements.add(myRandomRange(1,30));
}
tmp.listOfElements = listOfElements;
mySet.add(tmp);
}
return mySet;
}
}
和
import java.util.ArrayList;
public class Set {
public String name;
public int id;
public ArrayList<Integer> listOfElements;
public Set(String name, int id) {
this.name = name;
this.id = id;
listOfElements = new ArrayList<Integer>();
}
}