【发布时间】:2016-06-04 19:48:05
【问题描述】:
我正在尝试开发一个程序,给定一组节点和一组人都以整数作为键。
我需要找到所有可能的组合,让人们通过所有节点。一个人可以自己去所有的节点,也可以被不同的人分开。
由于人们是同质的,因此两个人以相同的顺序通过相同的节点,因此只能算作一个解决方案。
例如 Sol: Person 0= [1], Person1= [2], and Person 2= [3] 将等价于 Sol: Person 0 = [2], Person 1 = [1] and Person 2 = [3] 或 Sol: Person 0= [1], Person 1= [3, 2], Person 2= null 将等价于 Sol: , Person 1= [3, 2],Person 1= null ,Person 2= [1]。
我使用整数矩阵 Sol 的列表来存储所有可能的路径 Integer[person][nodes]。所以我想将解决方案存储在集合或列表中。那将是 Set 或 List。
所以 Sol[0]= 将等于 0 号人经过的所有节点。
如果我们有 3 个人 (0,1,2) 和 3(1,2,3) 节点,所有可能的解决方案将是:
> Sol 1:
Person 0= [1]
Person 1= [2]
Person 2= [3]
>Sol 2:
Person 0= [3]
Person 1= [2, 1]
Person 2= null
>Sol 3:
Person 0= [3]
Person 1= [1, 2]
Person 2= null
>Sol 4:
Person 0= [1]
Person 1= [3, 2]
Person 2= null
>Sol 5:
Person 0 = [1]
Person 1= [2, 3]
Person 2= null
>Sol 6:
Person 0 = [2]
Person 1= [1, 3]
Person 2= null
>Sol 7:
Person 0 = [2]
Person 1= [3, 1]
Person 2= null
>Sol 8:
Person 0 = [3, 2, 1]
Person 1= null
Person 2= null
>Sol 9:
Person 0 = [1, 2, 3]
Person 1= null
Person 2= null
>Sol 10:
Person 0 = [3, 1, 2]
Person 1= null
Person 2= null
>Sol 11:
Person 0 = [2, 1, 3]
Person 1= null
Person 2= null
>Sol 12:
Person 0 = [1, 3, 2]
Person 1= null
Person 2= null
>Sol 13:
Person 0 = [2, 3, 1]
Person 1= null
Person 2= null
面对这个问题,我的开始想法是开始使用所有节点为人 0 添加所有路径,从人 0 的路径中取出除 1 之外的所有节点并添加到人 1,然后全部取走人 0 中除 1 之外的节点,并将它们添加到人 1.. 等等。
然后我会调用用于从 Person 0 和 Person 1 组合生成路径的相同函数,并为 Person 1(之前生成的路径)和 Person 2 调用它。所以它对于递归算法(在我的意见)。
当我有两个人时,我得到了所有可能的解决方案,但我不知道如何为无限数量的人和节点实施它。
代码:
public static void function(List<Sol> solutions, int startingPerson, Integer[] people, List<Integer> Numbers, Sol part) {
Set<List<Integer>> result;
Set<List<Integer>> resResult;
int i = 0;
for (Integer j = Numbers.size(); j >= 0; j--) {
if (j == 1 && Numbers.size() <= people.length) {
for (int l = startingPerson; l < Numbers.size() + startingPerson; l++) {
Integer[] in2 = new Integer[1];
in2[0] = Numbers.get(l - startingPerson);
part.getSol()[l] = in2;
}
Arrays.fill(part.getSol(), null);
solutions.add(org.apache.commons.lang3.SerializationUtils.clone(part));
Arrays.fill(part.getSol(), null);
}
/*We get all combinations (order not important) of a certain number of the nodes*/
Combinations it = new Combinations(Numbers, i);
Iterator<List<Integer>> s = it.iterator();
Set<List<Integer>> l2 = new HashSet<>();
while (s.hasNext()) {
List<Integer> listares = s.next();
l2.add(listares);
}
/*In l2 we have all the combination so loop them to add them to the paths*/
for (List<Integer> l3 : l2) {
/*We get all possible permutations for the numbers of the combination */
result = permute(l3);
/*We loop all possible permutations*/
for (List<Integer> l4 : result) {
int k = startingPerson;
ArrayList<Integer> res = new ArrayList<>(Numbers);
res.removeAll(l4);
Integer[] array = new Integer[l4.size()];
l4.toArray(array);
//*We get all the permutations from res numbers*//
resResult = permute(res);
//*So we won't repeat same paths*//
if (!res.isEmpty() && (res.size() <= Math.nextUp(Numbers.size() / 2))) {
for (List<Integer> l5 : resResult) {
Integer[] array2 = new Integer[l5.size()];
l5.toArray(array2);
part.getSol()[k] = array2;
}
}
/*Means that we are only using a person to go through all the nodes*/
if (res.isEmpty()) {
part.getSol()[k] = array;
solutions.add(org.apache.commons.lang3.SerializationUtils.clone(part));
Arrays.fill(part.getSol(),null);
/*More than one person to go through the nodes*/
} else if (res.size() <= Math.nextUp(Numbers.size() / 2)) {
part.getSol()[k + 1] = array;
solutions.add(org.apache.commons.lang3.SerializationUtils.clone(part));
part.getSol()[k + 1] = null;
k++;
/*We only can take numbers from the combination if we have more than one element */
/*if(array.length>1) {
function(solutions, k, people, l4, part);
}*/
}
}
}
i++;
}
}
public static Set<List<Integer>> permute(List<Integer> ls) {
// we use a Set of Sets rather than a list of arrays
// because Sets support adding in the middle
// and track current length
Set<List<Integer>> permutations = new HashSet<>();
// Add an empty Set so that the middle for loop runs
permutations.add(new ArrayList<>());
for (int i = 0; i < ls.size(); i++) {
// create a temporary container to hold the new permutations
// while we iterate over the old ones
Set<List<Integer>> current = new HashSet<>();
for (List<Integer> permutation : permutations) {
for (int j = 0, n = permutation.size() + 1; j < n; j++) {
List<Integer> temp = new ArrayList<>(permutation);
temp.add(j, ls.get(i));
current.add(temp);
}
}
permutations = new HashSet<>(current);
}
return permutations;
}
public class Combinations implements Iterable<List<Integer>> {
private List<Integer> lista;
private Integer k;
public Combinations(List<Integer> s, Integer k) {
lista = s;
this.k = k;
}
@Override
public Iterator<List<Integer>> iterator() {
return new IteratorCombn(lista, k);
}
private class IteratorCombn implements Iterator<List<Integer>> {
private int actualSize, maxresult;
private Integer curIndex;
private Integer[] result;
private int[] indices;
private Integer[] arrayList;
private List<Integer> elem = null;
public IteratorCombn(List<Integer> s, Integer k) {
actualSize = k;// desde donde
curIndex = 0;
maxresult = k;
arrayList = new Integer[s.size()];
for (int i = 0; i < arrayList.length; i++) {
arrayList[i] = s.get(i);
}
this.result = new Integer[actualSize < s.size() ? actualSize : s.size()];
indices = new int[result.length];
for (int i = 0; i < result.length; i++) {
indices[i] = result.length - 2 - i;
}
}
public boolean hasNext() {
elem = null;
while ((elem == null && curIndex != -1)) {
if(indices.length==0){
return false;
}
indices[curIndex]++;
if (indices[curIndex] == (curIndex == 0 ? arrayList.length: indices[curIndex - 1])) {
indices[curIndex] = indices.length - curIndex - 2;
curIndex--;
} else {
result[curIndex] = arrayList[indices[curIndex]];
if (curIndex < indices.length - 1)
curIndex++;
else {
elem = new ArrayList<>(result.length);
for (Integer s : result) {
elem.add(s);
}
}
}
}
if (elem == null) {
if (actualSize < maxresult) {
actualSize++;
this.result = new Integer[actualSize < arrayList.length ? actualSize
: arrayList.length];
indices = new int[result.length];
for (int i = 0; i < result.length; i++) {
indices[i] = result.length - 2 - i;
}
curIndex = 0;
return this.hasNext();
} else {
return false;
}
} else {
return true;
}
}
@Override
public List<Integer> next() {
return elem;
}
@Override
public void remove() {
// TODO Auto-generated method stub
}
}
}
类 Sol 是一个只包含 Integer[][] sol 的类
我只使用一个矩阵,并且一直在更改它,因为我想节省 JVM 内存。
我想知道是否有人可以帮助我解决问题或给我另一个解决问题的想法。
谢谢。
【问题讨论】:
-
你的意思是任何人都可以经过零个或多个,还是所有节点,解决方案的唯一要求是每个节点都被访问一次?
-
一个人可以通过所有节点,但是两个人不能通过同一个节点。要求是所有节点都被某人访问。对不起,如果我没有很好地表达自己。
-
在这种情况下,您会错过许多其他可能的解决方案。例如,
person 0 = [2], person 1 = [1] and person 2 = [3]或person 0 = null, person 1 = [3,2] and person 2 = [1] -
因为所有人都是同质的,所以这个 sol ( Sol 1: Person 0= [1], Person1= [2], and Person 2= [3] ) 将等价于 Person 0 = [2 ], Person 1 = [1] and Person 2 = [3] 和 Sol 4 的第二个相同:Person 0= [1] Person 1= [3, 2] Person 2= null
-
这样看——每个节点都有一个选择,由哪个人来访问它。所以对于
n人和m节点,你有m * n!可能的解决方案。
标签: java algorithm matrix combinations permutation