最近我一直试图做一个问题,要求我找到所有不同的组合,每行只选择1个元素。例如,我输入n行,每行2个字符串。但是,我只想找到所有不同的组合,我从每行中选择1个字符串。
示例:
输入:
3
alex bob
straw mat
eat drink
示例组合: 亚历克斯秸秆饮料
这导致2 ^ n个组合,在这种情况下将是2 ^ 3 = 8个组合。但是,如果我使用n for循环来查找组合 例如
#include <iostream>
#include <cstring>
#include <string>
using namespace std;
int n;
int main(int argc, char ** argv) {
cin >> n; //rows of words
string words[n][2]; //the words with 2 words per row
for (int i = 0; i < n; i++) {
for (int j = 0; j < 2; j++) {
cin >> words[i][j]; //input of words
}
}
//finding all possible combinations
for (int i =0; i<n; i++){
for (int j=0; j<2; j++){
for (int x=0; x<2; x++){
//and so on per n
}
}
}
return 0;
}
这将需要n for循环来找出数组的所有组合,只从每一行中取一个项目。什么是最好和最简单的方法来找到大小为n的所有不同组合,因为我会从每行中的两个中取1个字符串?感谢。
答案 0 :(得分:2)
你可以做递归。
假设C ++ 11,这样的事情可能(虽然没有尝试编译):
// finding all possible combinations
std::vector<std::vector<std::string>> combinations;
const auto processLine = [&](const std::vector<std::string>& currentCombination, int line) {
std::vector<std::string> combination0 = currentCombination;
std::vector<std::string> combination1 = currentCombination;
combination0.push_back(words[line][0]);
combination1.push_back(words[line][1]);
if (line + 1 < n) {
// process next line
processLine(combination0, line + 1);
processLine(combination1, line + 1);
}
else {
// last line - keep the result
combinations.push_back(combination0);
combinations.push_back(combination1);
}
};
std::vector<std::string> empty;
processLine(empty, 0);
// print results
for (const auto& combination : combinations) {
for (const auto& word : combination) {
std::cout << word << " ";
}
std::cout << std::endl;
}
答案 1 :(得分:1)
对于每行总有2个元素的设置,一个非常简单的解决方案是使用数据类型整数并将每个位解释为相应行中第一列或第二列的决策;然后简单地从0到2 ^ n - 1计数以获得所有组合。 应用于您的示例,如下所示:
int bits meaning
0 000 alex,straw,eat
1 001 alex,straw,drink
2 010 alex,mat,eat
3 011 alex,mat,dring
4 100 bob,straw,eat
5 101 bob,straw,drink
6 110 bob,mat,eat
7 111 bob,mat,drink
对于任何给定的整数值0..7,使用位移运算符或&amp; -bitmask将每个位映射到列索引:
void getCombinationRepresentedByIntValue(vector<string>& combination, int value) {
int mask = 1;
for (int i=n-1; i>=0; i--) {
if (value & mask)
combination.push_back(words[i][1]);
else
combination.push_back(words[i][0]);
mask = mask << 1;
}
}
答案 2 :(得分:0)
这似乎回答了你的问题:
int ct[n]; // count of the number of pass
int current = 0; // index of the current word (n)
/* while not all combinaison have been exploited */
while (current >= 0)
{
cout << words[current][ct[current]]; /* <<<<< can be used another way*/
/* down to the next word */
current ++; // to get the next word
if (current >=n) { // at the end of the list
cout << " ";
current--; // restore last
ct[current]++; // increment number of time we passed
/* find the previous not completely exploited */
while (current >= 0 && ct[current]> 1) /* <<< change 1 to any number of words per line */
{
ct[current] = 0;
current--;
if (current >= 0) ct[current]++;
}
if (current > 0 ) current = 0;
}
}
用你的例子:
输入:
3 亚历克斯鲍勃 草席 吃喝?
输出: alexstraweat alexstrawdrink alexmateat alexmatdrink bobstraweat bobstrawdrink bobmateat bobmatdrink
希望它有所帮助!