给定1到N的范围,其中N> = 3。你得带走一个 长度为2N的数组并放置每个数字(从1到N的范围) 两次。这样一个数字的两个索引之间的距离是 等于数字。例子
N = 3
(3,1,2,1,3,2)
我想到的解决方案如下:
生成数字范围的每个排列数组,例如:{1,2,3 |,{3,2,1},{2,1,3}等
对于每个排列数组,运行以下函数:
foreach(int number : permutationArray){
addToResultArray(number);
}
addToResultArray(int toBeAdded){
for(int i = 0; i < resultArray.length; i++){
//-1 implies the resultArray is empty at that index
if(resultArray[i]==-1 && resultArray[i+toBeAdded+1]==-1)
resultArray[i] = toBeAdded;
}
}
如果上述功能不会导致越界异常,则您有一个有效的解决方案。
我不认为这个解决方案非常好。有没有人有更好的东西?
答案 0 :(得分:0)
这可以被视为一个受限制的问题:您有2*N
个变量V={v1,v2,...,v2n}
(表示数组索引)每个变量在约束下具有[1,2,..,N]
个可能的值:
赋值是从变量集到其可能值的映射。例如,[v1=1,v2=3,v3=5]
是v1,v2
和v3
的作业。如果满足约束,则给定的分配是 一致 。不一致赋值的示例是[v1=3,v2=1,v3=3]
如果基数等于变量大小(即2*N
),则分配完成。否则它是部分分配。显然,我们的目标是拥有一个或多个完全一致的任务(a.k.a解决方案)。
所以问题基本上是回溯搜索问题。特别是,我们对变量进行了排序。每次我们为当前变量赋值。如果该值使当前分配不一致,我们回溯。
您的方法实际上是generate-and-test效率低下。生成所有解决方案并对其进行计数通常是一个难题。在大多数情况下,我们正在寻找一种解决方案。
以下是有趣的部分:有一种更有效的方法可以通过传播值并更快地检测回溯来实现这一点(参见constraint propagation)。