好的,我需要为照片竞赛实现这个...我有一组主要的N张照片,我需要生成那些照片的第2张的排列,而不需要重复,例如:
foo.png VS bar.png
等于
bar.png VS foo.png
另一件事,我不能每次都预先生成排列,所以我需要一个函数,给定前一个排列,将返回下一个(如果可能的唯一排列结束,则返回NULL)。
我使用以下PHP函数解决了这个问题:
function getNextPermutation( $aPermutableItems, $iPermutationSize, $aPreviousPermutation = NULL )
{
$aNextPermutation = $aPreviousPermutation;
$iLastIndex = $iPermutationSize - 1;
$iPermutableItems = count($aPermutableItems);
// Any previous permutation ?
if( $aPreviousPermutation )
{
// Loop the elements backwards
for( $i = $iLastIndex; $i >= 0; $i-- )
{
// Can the current element be incremented without reaching the limit ?
if( ++$aNextPermutation[ $i ] >= $iPermutableItems )
{
// Increment the previous element
$iPrevValue = ++$aNextPermutation[ $i - 1 ];
// Reset the current element with the value of the previous plus one
$iNextValue = $aNextPermutation[ $i ] = $iPrevValue + 1;
// Skip the previous element because it was just incremented
$i--;
// If one of the two elements reached the limit, we are in the exit condition
if( $iPrevValue >= $iPermutableItems || $iNextValue >= $iPermutableItems )
return FALSE;
}
// Limit still to be reached for the i-th element, skip previous ones
else
break;
}
}
// Am i able to generate the first permutation ?
else if( $iPermutationSize <= $iPermutableItems )
$aNextPermutation = range( 0, $iLastIndex );
// Permutation impossible to generate because we don't have enough elements in the main set
else
$aNextPermutation = FALSE;
return $aNextPermutation;
}
那样:
$iPerm = 0;
$aPrev = NULL;
$aItems = array( 0, 1, 2, 3, 4 );
while( ($aPrev = getNextPermutation( $aItems, 2, $aPrev )) != FALSE )
{
echo sprintf( "%2d : %s\n", $iPerm++, implode( ', ', $aPrev ) );
}
将输出:
0 : 0, 1
1 : 0, 2
2 : 0, 3
3 : 0, 4
4 : 1, 2
5 : 1, 3
6 : 1, 4
7 : 2, 3
8 : 2, 4
9 : 3, 4
现在,我真的想为它添加一些熵...我的意思是,正如你所看到的,组合中的第一项经常重复(0,1 0,2 0,3),并且在我的情况下这不好,因为我会看到4个连续排列的相同图片。
有没有办法修改(或重新实现)我的算法以获得类似(例如)的内容:
0 : 0, 1
1 : 1, 2
2 : 0, 3
3 : 3, 4
4 : 0, 2
5 : 1, 3
6 : 0, 4
7 : 2, 3
8 : 2, 4
9 : 1, 4
显然我不能随意改变排列数组,因为正如我所写,我没有整个排列数组,只有先前的排列将在我的算法应用后给出下一个排列。
PS:每次挑战我都有大约500张照片,因此存储位掩码或类似的东西是不可接受的。
感谢。
答案 0 :(得分:1)
如果您希望以未排序的方式对大小k
进行一些排列,则可以在基数2中使用n位的计数器,并打印下一个值(具有k
1
)每次,例如大小为3(和k = 2)的计数器:
000
001
010
011
100
101
110
所以,你的输出将是011,101和110(实际上将转换为(1,2),(3,1),(3,2))它不是你想要的但是当计数器大小时增长,它会更明智,但使用这样的计数器是耗时的,但如果你的图片大小小于20它足够快(因为2 ^ 20 = 100万不大)。同样通过获得100这样的数字,您只需启动计数器并获得下一个值即可。此外,这只是可扩展的,以生成大小为k的排列。
答案 1 :(得分:1)
创建一个包含k个和N-k个零的数组。 然后使用C ++ std :: next_permutation算法,其工作原理如下:
例如, 从0 0 0 0 1 1 1
开始找到最右边的一个5,将其移动到位置4: 0 0 0 1 0 1 1
对其余部分进行排序: 0 0 0 1 0 1 1
找到最合适的位置6,将其移动到位置5: 0 0 0 1 1 0 1
对其余部分进行排序: 0 0 0 1 1 0 1
找到最右边的一个7,将其移动到位置6: 0 0 0 1 1 1 0
对其余部分进行排序: 0 0 0 1 1 1 0
找到最右边的一个4,将其移动到位置3: 0 0 1 0 1 1 0
对其余部分进行排序: 0 0 1 0 0 1 1
等等......