【问题标题】:Trying to develop a sort of permutation algorithm试图开发一种置换算法
【发布时间】:2012-03-10 19:37:21
【问题描述】:

我想开发以下 put 无法正确处理。 我有一个长度为 N 的向量。每个元素可以变成 0 到 K。这里 N 和 K 由用户给定。现在我正在尝试创建一个函数,我可以在其中遍历所有可能的解决方案。

假设 N 为 4 且 K = 2,那么我想遍历所有可能的排列 (?)。

我想用 0000 填充向量,测试它然后用 1000 填充向量,然后测试 0100 等等。

知道 0100 和 0010 是不同的,这一点很重要。 1100 和 0011 等也是如此。

需要特别注意的是,这是循环应该打印的内容(只要出现所有不同的可能序列,0001 或 1000 在 0000 之后等真的没关系)。

0000、1000、0100、0010、0001、1100、1010、1001、1110、1101、0111、0101、.....、2012、2211等。

我尝试了 for 循环的组合,但无法真正做到。 应用程序是 C++

请帮忙,tnx

【问题讨论】:

  • 顺序重要吗? (例如,1101 必须在 0002 之前)
  • 听起来,对于给定的 N,K... 打印 Base K+1 中的所有 N 位数字
  • 也许你应该试试 std::next_permutation?看看stackoverflow.com/questions/4972470/…
  • @innochenti std::next_permutation 所做的事情与他所描述的完全不同。

标签: c++


【解决方案1】:

我认为排列不是您要寻找的词。你说的是计数,所以你想要做的就是增加向量,就像你在一年级时做加法一样

First value   0 0 0 0
Add 1               1
              =======
Second Value  0 0 0 1
Add 1               1
              =======
Third Value   0 0 1 0

所以你会做这样的事情:

// returns false when you've seen all of the possible values for this vector
bool increment(std::vector<int> & vector, int k) {
  for (int i = 0; i < vector.size(); ++i) {
    int j = vector[i] + 1;
    if (j <= k) {
      vector[i] = j;
      return true; 
    }
    else vector[i] = 0;
    // and carry a 1 by looping back again
  }
  return false;
}

这将按以下顺序返回值,对于 k=1,假设您从向量 0000 开始:1000、0100、1100、0010、1010、0110、1110、0001、1001、0101、1101、0011、1011 , 0111, 1111。 (图片以二进制计数——我只是颠倒了每个数字,以适应我们对从左到右的向量的普通视图。)

【讨论】:

  • 不错 :) increment() 在溢出的情况下返回 false。所以用 while(increment(...)){...} 遍历所有排列
【解决方案2】:

我想到了这样的事情

bool increase(vector<int> &d, int index, int k){

  if(index == d.size()){
    return false;
  }

  if(d[index] == k){
    d[index] = 0;
    increase(d, index+1, k);
  }else{
    d[index]++;
  }

  return true;
}

void printvector(vector<int> v){
  cout<<" ";
  for(int i=0;i<v.size();i++){
    cout<<v[i];
 }
}

int main(){
//int N, K predefined, and initialised.

  vector<int> D(N, 0);

  do{
    printvector(d);
  }while(increase(d, 0, K);


}

【讨论】:

    【解决方案3】:

    您可能需要recursive 解决方案来巧妙地完成它。
    将所有可能性放在第一个元素上,并以递减的大小递归调用。

    伪代码:

    permutations(int n, int k, solution):
       if (n==0): //base clause
           print solution //or append to some extra data structure
           return
       for (i = 0 ; i <= k ; i++):
           solution.append(i)
           permutations(n-1,k,solution) //recursive call
           solution.removeLast() //clean up environment before moving to the next possibility
    

    使用permutations(n,k,v) 调用 - 其中n,k 是您的参数,v 是一个空的std::vector

    编辑:C++代码:

    void permutations(int n, int k,vector<int> &solution) {
       if (n==0) { //base clause
           print(solution);
           return;
       }
       for (int i = 0 ; i <= k ; i++) {
           solution.push_back(i);
           permutations(n-1,k,solution); //recursive call
           solution.pop_back(); //clean up environment before moving to the next possibility
       }
    }
    

    可以在here找到包含print()函数的演示

    【讨论】:

    • 非常感谢您对迟到的回复感到抱歉。这适用于小问题,但是当我尝试解决大问题时,递归不是可行的方法。有人可以帮助做同样的事情但使用动态编程吗?
    • @Michiel:不客气。您要求所有排列,其中有指数数量,任何产生所有排列的算法都将受到长时间运行的影响。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-15
    相关资源
    最近更新 更多