我有一个3乘3的布尔值网格,我对我可以拥有三个“活”单元格的方式感兴趣(根据我的计算,有56个排列)。旋转对称并不重要,但活细胞彼此难以区分。
假设我在网格中相对于质心索引值:
-------------------
|-1,-1| 0,-1| 1,-1|
-------------------
|-1,0 | | 1,0 |
-------------------
|-1,1 | 0,1 | 1,1 |
-------------------
有一个很好的循环可以用来计算56个排列吗? (我刚刚完成了所有输入,我很想知道我是否可以稍微聪明一些)。
我正在使用C ++,但如果很清楚,基本算法在任何语言或伪语言中都会很精彩。
答案 0 :(得分:4)
您可以使用next_permutation。
例如,假设字符串下面x中的每个字符表示网格中的一个单元格(质心单元格除外)从左上角开始并向右下方开始。您可以运行此代码以查找所有可能的排列,并且在循环内,字符串x将表示可能的排列,其中1是活动单元格,0是死亡单元格。
int main() {
string x = "00000111";
int cnt = 0;
do {
++cnt;
// do something useful with this configuration...
} while(next_permutation(x.begin(),x.end()));
cout<<cnt<<endl;
return 0;
}
答案 1 :(得分:1)
从维基百科尝试this procedure。
以下算法在给定排列后按字典顺序生成下一个排列。它就地改变了给定的排列。
- 找到最大的索引k,使得a [k]&lt; a [k + 1]。如果不存在这样的索引,则排列是最后的排列。
- 找到最大的索引l,使得a [k]&lt;一个[1]。由于k + 1是这样的指数,因此l被很好地定义并且满足k <1。升。
- 用[l]交换[k]。
- 将序列从[k + 1]反转到最后一个元素a [n]。
醇>
答案 2 :(得分:0)
你可以使用这种方法:
假设您使用数组表示网格,其中元素为
[(-1,-1), (0,-1),(1,-1)...]
等等,你基本上把元素放在第一行,然后是第二行,然后是第三行。
所以现在,你只需要拿走你拥有的所有可用数字,也就是说:
[1,1,1,0,0,0,0,0,0]
正如你所说,你只需要3个活细胞。
现在我们决定了不同的字符串意味着,你可以简单地选择一个执行排列的代码,就像这个链接上的xcellnt一样How To Generate Permutation In C? 这完全符合你的要求,或者算法库中的std :: next_permutation之类的任何等效代码。
答案 3 :(得分:0)
您更喜欢“更智能”循环或“ saner ”吗?
//c++ --std=c++11 test.cc
#include <iostream>
#include <string>
#include <list>
#include <vector>
#include <algorithm>
#include <utility>
using std::string;
using std::list;
using std::vector;
const string show[8] = { "(-1,-1)","( 0,-1)","( 1,-1)"
, "(-1, 0)", "( 1, 0)"
, "(-1, 1)","( 0, 1)","( 1, 1)"
};
auto permutations_of_living_cells =
[] (int number_of_living_cells) -> list<vector<string>>
{
typedef list<vector<string>> (*recT)( void*
, int
, int
, vector<string> &&
, list<vector<string>> &&
);
recT rec = []( void*r
, int n
, int i
, vector<string> && prefix
, list<vector<string>> && l
) -> list<vector<string>>
{
if( n==0 )
{
l.push_back(std::move(prefix));
return std::move(l);
}
if( i>8-n ) return std::move(l);
vector<string> psi(prefix);
psi.push_back(show[i]);
return ((recT)r)(r,n ,i+1,std::move(prefix),
((recT)r)(r,n-1,i+1,std::move(psi ),
std::move(l)
)
);
};
return rec( (void*)rec
, number_of_living_cells
, 0
, vector<string>()
, list<vector<string>>()
);
};
template<class T>
std::ostream& operator<<( std::ostream & out,const vector<T> & v )
{
if( v.empty() ) return out << "[]";
out << "[ " << *v.begin();
std::for_each( v.begin()+1, v.end(), [&](T x){out<<", "<<x;} );
return out << " ]";
}
int main()
{
for( auto v : permutations_of_living_cells(3) )
std::cout << v << "\n";
std::cout << std::flush;
return 0;
}