问题与在C++中将组合分离为向量相关。

huangapple go评论74阅读模式
英文:

Issue with Separating Combinations into Vectors in C+

问题

我有一个包含16对符号和颜色的向量,其中有4种不同的颜色和4种不同的符号。我需要将这些组合分成4个不同的向量,并满足以下条件:

  1. 一个符号不能与同一向量中的另一个符号具有相同的颜色。
  2. 一个颜色不能与同一向量中的另一个颜色具有相同的符号。
  3. 符号和颜色的组合在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 &lt;iostream&gt;
#include &lt;vector&gt;
#include &lt;algorithm&gt;
#include &lt;cstdlib&gt;
#include &lt;ctime&gt;
using namespace std;
vector&lt;char&gt; symbols = {&#39;&amp;&#39;, &#39;#&#39;, &#39;%&#39;, &#39;$&#39;};
vector&lt;char&gt; colors = {&#39;R&#39;, &#39;G&#39;, &#39;B&#39;, &#39;Y&#39;};
vector&lt;pair&lt;char, char&gt;&gt; combinations;
void separateVectors() {
// Shuffle the combinations randomly
srand(time(0));
random_shuffle(combinations.begin(), combinations.end());
vector&lt;vector&lt;pair&lt;char, char&gt;&gt;&gt; vectors(4); // Store the four separate vectors
for (const auto&amp; 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 &lt; 4; i++) {
bool valid = true;
// Check if the symbol or color already exists in the current vector
for (const auto&amp; 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&#39;t be assigned to any vector, print a warning
if (!assigned) {
cout &lt;&lt; &quot;Warning: Combination (&quot; &lt;&lt; combination.first &lt;&lt; &quot;, &quot; &lt;&lt; combination.second &lt;&lt; &quot;) couldn&#39;t be assigned.&quot; &lt;&lt; endl;
}
}
// Print the four separate vectors
for (int i = 0; i &lt; 4; i++) {
cout &lt;&lt; &quot;Vector &quot; &lt;&lt; i &lt;&lt; endl;
for (const auto&amp; pair : vectors[i]) {
cout &lt;&lt; &quot;Symbol: &quot; &lt;&lt; pair.first &lt;&lt; &quot; Color: &quot; &lt;&lt; pair.second &lt;&lt; endl;
}
cout &lt;&lt; endl;
}
}
int main() {
// Generate all possible combinations
for (const auto&amp; symbol : symbols) {
for (const auto&amp; 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: &amp; Color: B
Symbol: % Color: G
Vector 1
Symbol: # Color: R
Symbol: &amp; Color: Y
Symbol: % Color: B
Symbol: $ Color: G
Vector 2
Symbol: # Color: G
Symbol: % Color: Y
Symbol: &amp; Color: R
Symbol: $ Color: B
Vector 3
Symbol: &amp; 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&#39;t be assigned.
Warning: Combination (&amp;, B) couldn&#39;t be assigned.
Vector 0
Symbol: # Color: G
Symbol: $ Color: B
Symbol: % Color: R
Symbol: &amp; Color: Y
Vector 1
Symbol: # Color: B
Symbol: &amp; Color: G
Symbol: % Color: Y
Symbol: $ Color: R
Vector 2
Symbol: % Color: G
Symbol: &amp; 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&amp; gen, std::vector&lt;Item&gt;&amp; items,
std::array&lt;std::vector&lt;Item&gt;, 4&gt;&amp; buckets) {
std::shuffle(begin(buckets), end(buckets), gen);
for (auto&amp; b : buckets) std::shuffle(begin(b), end(b), gen);
auto const i = std::uniform_int_distribution&lt;std::size_t&gt;(0, 3)(gen);
if (buckets[i].empty()) return false;
auto const k =
std::uniform_int_distribution&lt;std::size_t&gt;(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&amp; gen, std::vector&lt;Item&gt;&amp; items,
std::array&lt;std::vector&lt;Item&gt;, 4&gt;&amp; buckets) {
std::shuffle(begin(buckets), end(buckets), gen);
for (auto&amp; b : buckets) std::shuffle(begin(b), end(b), gen);
auto const i = std::uniform_int_distribution&lt;std::size_t&gt;(0, 3)(gen);
if (buckets[i].empty()) return false;
auto const k =
std::uniform_int_distribution&lt;std::size_t&gt;(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( "&amp;#%$", "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 &lt;iostream&gt;
#include &lt;vector&gt;
using namespace std;
//----------------------------------------------------------------------
vector&lt; vector&lt;string&gt; &gt; getCombinations( string symbols, string colours )
{
int N = symbols.size();
vector&lt; vector&lt;string&gt; &gt; result;
for ( int c = 0; c &lt; N; c++ )
{
vector&lt;string&gt; V( N );
for ( int i = 0; i &lt; 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&lt; vector&lt;string&gt; &gt; combinations = getCombinations( &quot;&amp;#%$&quot;, &quot;RGBY&quot; );
for ( int i = 0; i &lt; combinations.size(); i++ )
{
cout &lt;&lt; &quot;\nVector &quot; &lt;&lt; i &lt;&lt; &#39;\n&#39;;
for ( string s : combinations[i] ) cout &lt;&lt; &quot;Symbol: &quot; &lt;&lt; s[0] &lt;&lt; &quot; Colour: &quot; &lt;&lt; s[1] &lt;&lt; &#39;\n&#39;;
}
}

Output:

Vector 0
Symbol: &amp; Colour: R
Symbol: # Colour: G
Symbol: % Colour: B
Symbol: $ Colour: Y
Vector 1
Symbol: &amp; Colour: G
Symbol: # Colour: B
Symbol: % Colour: Y
Symbol: $ Colour: R
Vector 2
Symbol: &amp; Colour: B
Symbol: # Colour: Y
Symbol: % Colour: R
Symbol: $ Colour: G
Vector 3
Symbol: &amp; Colour: Y
Symbol: # Colour: R
Symbol: % Colour: G
Symbol: $ Colour: B

huangapple
  • 本文由 发表于 2023年6月13日 01:58:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/76459189.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定