使用2 ^ n步骤来获得房间中每个人的可能组合

时间:2012-05-12 10:39:57

标签: algorithm data-structures backtracking

这是消费税:

  

你从一个空房间开始,一群n个人在外面等着。在每一步,您可以允许一个人进入房间,或者让一个人进入房间。你能安排一个2 n 步骤的序列,这样每个人的可能组合都可以完成一次吗?


我的解决方案是:

我可以有一个具有 n 元素的位数组。每个元素的状态代表这个人是否在房间里。所以我们完全会在房间内有2个 n 不同的人组合。

该算法可以是标准的回溯,列出所有组合。


我只是想知道我的想法是太天真还是简单?

这个消费税中的任何陷阱?


修改

对于对gray code的实施感兴趣的人,请参阅

http://yagni.com/graycode/

4 个答案:

答案 0 :(得分:12)

  

该算法可以作为标准回溯列出所有组合。

您的解决方案“有效”,但如果天真地实施,则需要大于2个 n 步骤。

请参阅问题陈述中的以下句子:

  

在每一步中,您可以允许一个人进入房间,或者让一个人离开。

在您的解决方案中,当您列出所有位向量时,您可能会0111后跟1000,这意味着三个人将不得不离开房间,而一个人将不得不输入

这需要4个步骤,而不是一个步骤,因此您将获得超过2个 n 步骤来运行所有组合。

然而,可以排列您描述的位向量,使得两个连续向量之间只有一位不同。这就是所谓的Gray code

以下是维基百科文章的一个例子:

Dec  Gray   Binary
 0   000    000
 1   001    001
 2   011    010
 3   010    011
 4   110    100
 5   111    101
 6   101    110
 7   100    111

注意

  1. 涵盖所有位向量,
  2. 对于每个连续的向量,只有一位发生变化。
  3. 这意味着您将能够在2个 n 步骤中迭代所有组合。

    如何实现这样的序列生成器也在维基百科页面中进行了解释,但如果这是一个练习,我建议你在偷看之前自己尝试;)

答案 1 :(得分:3)

您正在寻找Gray code序列生成器。格雷码序列中的相邻值仅相差一位。

答案 2 :(得分:1)

以下是格雷码序列生成的工作代码

// Binary Reflected Gray Code
void brgc( int *a, int n, int idx, int reflect )
{
    if ( n == idx ) {
        printIntArr( a, n );
    } else {
        a[ idx ] = reflect;
        brgc( a, n, idx + 1, 0 );
        a[ idx ] = !reflect;
        brgc( a, n, idx + 1, 1 );
    }
}

int main( int argc, char *argv[] )
{
    if ( argc != 2 ) {
        printf( "Usage...\n" );
        return -1;
    }
    int n = atoi( argv[ 1 ] );
    int *a = malloc( sizeof( int ) * n );
    brgc( a, n, 0, 0 );
}

答案 3 :(得分:0)

/ package whatever; // don't place package name! /

import java.util.*;
import java.lang.*;
import java.io.*;

/ Name of the class has to be "Main" only if the class is public. /
class Ideone
{
    public static void main (String[] args) throws java.lang.Exception
    {
        int numberofPeople=3;
        int size = 1<<numberofPeople;
        for(int i=0;i<size;i++)
        {
            int num = i^(i>>1);
            System.out.println(Integer.toBinaryString(num));
        }
    }
}