英文:
Issue with Separating Combinations into Vectors in C+
问题
我有一个包含16对符号和颜色的向量,其中有4种不同的颜色和4种不同的符号。我需要将这些组合分成4个不同的向量,并满足以下条件:
- 一个符号不能与同一向量中的另一个符号具有相同的颜色。
- 一个颜色不能与同一向量中的另一个颜色具有相同的符号。
- 符号和颜色的组合在4个向量中只能使用一次。
我已经尝试在C++中实现这个分离逻辑,但遇到了一个问题,有时候一些组合没有分配到任何向量中,尽管理论上应该是可以分配的。
我已经尝试使用random_shuffle随机打乱组合并检查逻辑的有效性。然而,问题仍然存在,我无法确定原因。
请问有人能够帮助我识别问题并提供解决方案,以确保所有组合都分配到向量中并满足给定的条件吗?我非常感谢任何指导或建议。谢谢!
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstdlib>
#include <ctime>
using namespace std;
vector<char> symbols = {'&', '#', '%', '$'};
vector<char> colors = {'R', 'G', 'B', 'Y'};
vector<pair<char, char>> combinations;
void separateVectors() {
// 随机打乱组合
srand(time(0));
random_shuffle(combinations.begin(), combinations.end());
vector<vector<pair<char, char>>> vectors(4); // 存储四个不同的向量
for (const auto& combination : combinations) {
bool assigned = false; // 标志,指示是否已分配组合
// 遍历向量以找到当前组合的合适向量
for (int i = 0; i < 4; i++) {
bool valid = true;
// 检查符号或颜色是否已经存在于当前向量中
for (const auto& pair : vectors[i]) {
if (pair.first == combination.first || pair.second == combination.second) {
valid = false;
break;
}
}
// 如果组合满足条件,将其添加到当前向量并更新标志
if (valid) {
vectors[i].push_back(combination);
assigned = true;
break;
}
}
// 如果组合无法分配到任何向量中,打印警告
if (!assigned) {
cout << "Warning: Combination (" << combination.first << ", " << combination.second << ") couldn't be assigned." << endl;
}
}
// 打印四个不同的向量
for (int i = 0; i < 4; i++) {
cout << "Vector " << i << endl;
for (const auto& pair : vectors[i]) {
cout << "Symbol: " << pair.first << " Color: " << pair.second << endl;
}
cout << endl;
}
}
int main() {
// 生成所有可能的组合
for (const auto& symbol : symbols) {
for (const auto& color : colors) {
combinations.push_back(make_pair(symbol, color));
}
}
separateVectors();
return 0;
}
期望输出:
期望的输出应该是四个不同的向量,每个包含四个符号和颜色的组合,满足给定的条件。
示例:
Vector 0
Symbol: # Color: Y
Symbol: $ Color: R
Symbol: & Color: B
Symbol: % Color: G
Vector 1
Symbol: # Color: R
Symbol: & Color: Y
Symbol: % Color: B
Symbol: $ Color: G
Vector 2
Symbol: # Color: G
Symbol: % Color: Y
Symbol: & Color: R
Symbol: $ Color: B
Vector 3
Symbol: & Color: G
Symbol: # Color: B
Symbol: $ Color: Y
Symbol: % Color: R
当前输出:
当前输出未将一些组合分配到任何向量中,尽管理论上应该可以分配。
示例:
Warning: Combination ($, Y) couldn't be assigned.
Warning: Combination (&, B) couldn't be assigned.
Vector 0
Symbol: # Color: G
Symbol: $ Color: B
Symbol: % Color: R
Symbol: & Color: Y
Vector 1
Symbol: # Color: B
Symbol: & Color: G
Symbol: % Color: Y
Symbol: $ Color: R
Vector 2
Symbol: % Color: G
Symbol: & Color: R
Symbol: # Color: Y
Vector 3
Symbol: % Color: B
Symbol: $ Color: G
Symbol: # Color: R
附加说明:
我已验证了检查有效性并将组合分配给向量的逻辑,但问题仍然存在。问题只有大约50%的时间会出现,大多数情况下,组合会丢失在向量2和3中,偶尔在0和1中。有时最多有5个组合无法分配,但大多数情况下只有一个或两个。
我非常感谢任何关于解决这个问题的见解、建议或解决方案。谢谢您提前的帮助!
英文:
I have a vector of 16 pairs of symbols and colors, where there are 4 different colors and 4 different symbols. I need to separate these combinations into 4 different vectors, with the following conditions:
A symbol cannot have the same color as another symbol in the same vector.
A color cannot have the same symbol as another color in the same vector.
A combination of symbol and color can only be used once in the 4 vectors.
I have tried implementing the separation logic in C++, but I'm encountering an issue where sometimes, some combinations are not being assigned to any vector, even though it should be possible to assign them.
I have already tried shuffling the combinations randomly using random_shuffle and have checked the logic for validity. However, the problem still persists, and I'm unable to identify the cause.
Could someone please help me identify the issue and provide a solution to ensure that all combinations are assigned to the vectors while satisfying the given conditions? I appreciate any guidance or suggestions. Thank you!
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstdlib>
#include <ctime>
using namespace std;
vector<char> symbols = {'&', '#', '%', '$'};
vector<char> colors = {'R', 'G', 'B', 'Y'};
vector<pair<char, char>> combinations;
void separateVectors() {
// Shuffle the combinations randomly
srand(time(0));
random_shuffle(combinations.begin(), combinations.end());
vector<vector<pair<char, char>>> vectors(4); // Store the four separate vectors
for (const auto& combination : combinations) {
bool assigned = false; // Flag to indicate if the combination has been assigned
// Iterate over the vectors to find a suitable one for the current combination
for (int i = 0; i < 4; i++) {
bool valid = true;
// Check if the symbol or color already exists in the current vector
for (const auto& pair : vectors[i]) {
if (pair.first == combination.first || pair.second == combination.second) {
valid = false;
break;
}
}
// If the combination satisfies the conditions, add it to the current vector and update the flag
if (valid) {
vectors[i].push_back(combination);
assigned = true;
break;
}
}
// If the combination couldn't be assigned to any vector, print a warning
if (!assigned) {
cout << "Warning: Combination (" << combination.first << ", " << combination.second << ") couldn't be assigned." << endl;
}
}
// Print the four separate vectors
for (int i = 0; i < 4; i++) {
cout << "Vector " << i << endl;
for (const auto& pair : vectors[i]) {
cout << "Symbol: " << pair.first << " Color: " << pair.second << endl;
}
cout << endl;
}
}
int main() {
// Generate all possible combinations
for (const auto& symbol : symbols) {
for (const auto& color : colors) {
combinations.push_back(make_pair(symbol, color));
}
}
separateVectors();
return 0;
}
Expected Output:
The expected output should be four separate vectors, each containing four combinations of symbol and color, satisfying the given conditions.
Example:
Vector 0
Symbol: # Color: Y
Symbol: $ Color: R
Symbol: & Color: B
Symbol: % Color: G
Vector 1
Symbol: # Color: R
Symbol: & Color: Y
Symbol: % Color: B
Symbol: $ Color: G
Vector 2
Symbol: # Color: G
Symbol: % Color: Y
Symbol: & Color: R
Symbol: $ Color: B
Vector 3
Symbol: & Color: G
Symbol: # Color: B
Symbol: $ Color: Y
Symbol: % Color: R
Current Output:
The current output is not assigning some combinations to any vector, even though it should be possible to assign them.
Example:
Warning: Combination ($, Y) couldn't be assigned.
Warning: Combination (&, B) couldn't be assigned.
Vector 0
Symbol: # Color: G
Symbol: $ Color: B
Symbol: % Color: R
Symbol: & Color: Y
Vector 1
Symbol: # Color: B
Symbol: & Color: G
Symbol: % Color: Y
Symbol: $ Color: R
Vector 2
Symbol: % Color: G
Symbol: & Color: R
Symbol: # Color: Y
Vector 3
Symbol: % Color: B
Symbol: $ Color: G
Symbol: # Color: R
Additional Notes:
I have verified the logic for checking validity and assigning combinations to vectors, but the issue still persists. The issue only occurs like 50% of the time, most of the time, the combinations are missing from the vector 2 and 3, rarely from 0 and 1. Sometimes there are up to 5 combinations not assigning but most of the time it's only one or two.
I would greatly appreciate any insights, suggestions, or solutions to resolve this problem. Thank you in advance for your help!
答案1
得分: 0
以下是您要翻译的内容:
问题在于您的算法是贪婪的,会导致您陷入局部最小值(死胡同)。在您的结果中,$Y 不能放入任何一个桶中,因为每个桶都要么有一个$符号,要么有一个Y颜色。然而,如果您看一下桶0,您会注意到它包含$B,这个$B 可以 放入桶2。如果您还将&Y 移入桶3,实际上可以将$Y 放入桶0。
- 您可以尝试构建一个增广逻辑,可以识别这些情况并移动已经放置的物品(有一个想法,可以参考:Diniz 或 Dijkstra)。
- 或者,您可以使用一个随机算法,只是随机尝试将物品移动到未满的桶中,以便为无法放置的物品腾出空间。您可以在只剩下无法放置的物品时启动此算法(有一个想法,可以参考:模拟退火)。
这里 是一个示例,以非常基本的方式模拟了模拟退火。它平均在17轮内收敛到一个完美的解决方案:
std::mt19937 gen(0);
while (true) {
greedy(combinations, buckets); // straightforward greedy algorithm
if (combinations.empty()) break;
extract_random(gen, combinations, buckets);
}
inline bool extract_random(std::mt19937& gen, std::vector<Item>& items,
std::array<std::vector<Item>, 4>& buckets) {
std::shuffle(begin(buckets), end(buckets), gen);
for (auto& b : buckets) std::shuffle(begin(b), end(b), gen);
auto const i = std::uniform_int_distribution<std::size_t>(0, 3)(gen);
if (buckets[i].empty()) return false;
auto const k =
std::uniform_int_distribution<std::size_t>(0, buckets[i].size() - 1)(gen);
items.push_back(std::exchange(buckets[i][k], buckets[i].back()));
buckets[i].pop_back();
return true;
}
英文:
The problem is that your algorithm is greedy, leading you into local minima (dead ends). In your result $Y cannot be placed into any of the buckets because each has either a $ symbol or a Y colour. However, if you look at the bucket 0 you notice that it contains $B, which could be placed in bucket 2. If you also move &Y into bucket 3, you can actually place $Y into bucket 0.
- You could try to construct an augmenting logic that can identify these situations and move already placed items around (for an idea have a look at: Diniz or Dijkstra).
- Alternatively, you can use a randomised algorithm that just randomly tries moving items to not-full buckets in order to maybe make space for unplaceable items. You could start this algorithm once you have only unplaceable items left (for an idea have a look at: simulated annealing).
Here is an example that mimics simulated annealing in a very rudimentary fashion. It converges to a perfect solution in an average of 17 rounds:
std::mt19937 gen(0);
while (true) {
greedy(combinations, buckets); // straightforward greedy algorithm
if (combinations.empty()) break;
extract_random(gen, combinations, buckets);
}
inline bool extract_random(std::mt19937& gen, std::vector<Item>& items,
std::array<std::vector<Item>, 4>& buckets) {
std::shuffle(begin(buckets), end(buckets), gen);
for (auto& b : buckets) std::shuffle(begin(b), end(b), gen);
auto const i = std::uniform_int_distribution<std::size_t>(0, 3)(gen);
if (buckets[i].empty()) return false;
auto const k =
std::uniform_int_distribution<std::size_t>(0, buckets[i].size() - 1)(gen);
items.push_back(std::exchange(buckets[i][k], buckets[i].back()));
buckets[i].pop_back();
return true;
}
答案2
得分: 0
为什么不简单地循环排列颜色(例如)并输出一个明确生成的集合,而不依赖于随机化(正如已经指出的那样),随机化会导致死局。
#include <iostream>
#include <vector>
using namespace std;
//----------------------------------------------------------------------
vector< vector<string> > getCombinations( string symbols, string colours )
{
int N = symbols.size();
vector< vector<string> > result;
for ( int c = 0; c < N; c++ )
{
vector<string> V( N );
for ( int i = 0; i < N; i++ ) V[i] = V[i] + symbols[i] + colours[i];
result.push_back( V );
colours = colours.substr( 1 ) + colours[0]; // 循环旋转
}
return result;
}
//----------------------------------------------------------------------
int main()
{
vector< vector<string> > combinations = getCombinations( "&#%$", "RGBY" );
for ( int i = 0; i < combinations.size(); i++ )
{
cout << "\nVector " << i << '\n';
for ( string s : combinations[i] ) cout << "Symbol: " << s[0] << " Colour: " << s[1] << '\n';
}
}
输出:
Vector 0
Symbol: & Colour: R
Symbol: # Colour: G
Symbol: % Colour: B
Symbol: $ Colour: Y
Vector 1
Symbol: & Colour: G
Symbol: # Colour: B
Symbol: % Colour: Y
Symbol: $ Colour: R
Vector 2
Symbol: & Colour: B
Symbol: # Colour: Y
Symbol: % Colour: R
Symbol: $ Colour: G
Vector 3
Symbol: & Colour: Y
Symbol: # Colour: R
Symbol: % Colour: G
Symbol: $ Colour: B
英文:
Why don't you simply cyclically permute the colours (say) and output an explicitly-generated collection, rather than relying on randomisation (which, as already pointed out) leads to dead ends.
#include <iostream>
#include <vector>
using namespace std;
//----------------------------------------------------------------------
vector< vector<string> > getCombinations( string symbols, string colours )
{
int N = symbols.size();
vector< vector<string> > result;
for ( int c = 0; c < N; c++ )
{
vector<string> V( N );
for ( int i = 0; i < N; i++ ) V[i] = V[i] + symbols[i] + colours[i];
result.push_back( V );
colours = colours.substr( 1 ) + colours[0]; // cyclic rotation
}
return result;
}
//----------------------------------------------------------------------
int main()
{
vector< vector<string> > combinations = getCombinations( "&#%$", "RGBY" );
for ( int i = 0; i < combinations.size(); i++ )
{
cout << "\nVector " << i << '\n';
for ( string s : combinations[i] ) cout << "Symbol: " << s[0] << " Colour: " << s[1] << '\n';
}
}
Output:
Vector 0
Symbol: & Colour: R
Symbol: # Colour: G
Symbol: % Colour: B
Symbol: $ Colour: Y
Vector 1
Symbol: & Colour: G
Symbol: # Colour: B
Symbol: % Colour: Y
Symbol: $ Colour: R
Vector 2
Symbol: & Colour: B
Symbol: # Colour: Y
Symbol: % Colour: R
Symbol: $ Colour: G
Vector 3
Symbol: & Colour: Y
Symbol: # Colour: R
Symbol: % Colour: G
Symbol: $ Colour: B
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论