组和游戏算法

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

Group and Game Algorithm

问题

我在考虑一种算法,将游戏分配给对手的配对,他们会玩这个游戏。

我有x个对手和y个游戏(我认为y应该是x - 1,但我不确定)
每个对手应该每场比赛都参加一次,如果可能的话,应该对每个对手进行一次比赛。

我想要的是一个分组配对的列表,分配给一个游戏。
总游戏数应该尽量少。

以4个对手“A,B,C,D”和3场比赛为例:

对手1 游戏 对手2
A 1 B
A 2 C
A 3 D
B 2 C
B 3 D
C 1 D

在这里,每个对手都与另一个对手比赛一次,每个对手都参加每场比赛一次。

尝试手动解决5名对手和4场比赛已经很复杂。

那么7名对手和6场比赛呢?
这是否可能?

我尝试手动解决这个问题,然后发现这太复杂了。

之后,我考虑了如何可能使用算法来解决它,但我想不出解决方案。
我想也许一个尝试最小化总游戏数的图算法可以有所帮助。

英文:

I am thinking of an algorithm that assign games to pairs of opponents which play the game.

I have x opponents and y games (I think y should be x - 1, but I am not sure)
Every opponent should play each game once and if possible play against every opponent once.

What I want is a list of group pairings assigned to a game.
The number of games overall should be minimal.

An example with 4 opponents A, B, C, D and 3 games:

Opp1 Game Opp2
A 1 B
A 2 C
A 3 D
B 2 C
B 3 D
C 1 D

Here, each opponent plays against another opponent exactly once, and every opponent plays each game exactly once.

Trying that manually for 5 opponents and 4 games already gets complex.

How about 7 opponents and 6 games?
Is that possible at all?

I tried that to solve the problem manually, then I found out that this is too complex.

After that I thought about how I could maybe solve it using an algorithm, but I could not come up with a solution.
I thought maybe a graph algorithm which tries to minimize the overall games count could help.

答案1

得分: 1

以下是翻译好的部分:

  • 循环 Op1 遍历组(例如 A、B、C 等)
    • 循环 Op2 遍历组,从 Op1 + 1 开始(例如 B、C 等)
      • 循环 G 遍历游戏
        • 如果 Op1 和 Op2 都没有参加游戏 G
          • 在游戏 G 中分配 Op1 与 Op2
          • 从 G 循环中退出

以下是C++代码:

#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
#include <vector>
#include <algorithm>

class cMatchMaker
{
public:
    void ParseCommand(int argc, char *argv[])
    {
        if (argc != 3)
            exit(1);
        groupCount = atoi(argv[1]);
        gameCount = atoi(argv[2]);
    }
    void ConstructGroups()
    {
        for (int kg = 0; kg < groupCount; kg++)
        {
            std::string s({'A' + kg});
            vGroup.push_back(s);
            vGroupHasPlayed.push_back({});
        }
    }
    void ConstructGames()
    {
        for (int kg = 0; kg < gameCount; kg++)
        {
            vGame.push_back(std::to_string(kg + 1));
        }
    }

    void MakeMatches()
    {
        // 遍历组
        for (kop1 = 0; kop1 < groupCount; kop1++)
        {
            // 遍历可能的对手
            for (kop2 = kop1 + 1; kop2 < groupCount; kop2++)
            {
                // 遍历游戏
                for (auto &game : vGame)
                {
                    // 检查两个组都没有参加游戏
                    if (!HasGameBeenPlayed(
                            game))
                    {
                        // 我们有一个比赛!
                        DisplayMatch(
                            game);

                        // 记住谁参加了哪场比赛
                        Remember(
                            game);

                        break;
                    }
                }
            }
        }
    }

private:
    int groupCount, gameCount;
    std::vector<std::string> vGroup, vGame;
    std::vector<std::vector<std::string>> vGroupHasPlayed;
    int kop1, kop2;

    bool HasGameBeenPlayed(
        const std::string &game)
    {
        if (std::find(
                vGroupHasPlayed[kop1].begin(),
                vGroupHasPlayed[kop1].end(),
                game) != vGroupHasPlayed[kop1].end())
            return true;
        if (std::find(
                vGroupHasPlayed[kop2].begin(),
                vGroupHasPlayed[kop2].end(),
                game) != vGroupHasPlayed[kop2].end())
            return true;
        return false;
    }

    void DisplayMatch(
        const std::string &game)
    {
        std::cout << " | " << vGroup[kop1]
                  << " | " << game << " | "
                  << vGroup[kop2] << " |\n";
    }

    void Remember(
        const std::string &game)
    {
        vGroupHasPlayed[kop1].push_back(game);
        vGroupHasPlayed[kop2].push_back(game);
    }
};

main(int argc, char *argv[])
{
    cMatchMaker theMatchMaker;

    theMatchMaker.ParseCommand(argc, argv);
    theMatchMaker.ConstructGroups();
    theMatchMaker.ConstructGames();
    theMatchMaker.MakeMatches();

    return 0;
}

以下是7和6的输出:

 | Op1 | 游戏 | Op2 |
| ---|---|---|
| A | 1 | B |
| A | 2 | C |
| A | 3 | D |
| A | 4 | E |
| A | 5 | F |
| A | 6 | G |
| B | 3 | C |
| B | 2 | D |
| B | 5 | E |
| B | 4 | F |
| C | 1 | D |
| C | 6 | E |
| C | 4 | G |
| D | 6 | F |
| D | 5 | G |
| E | 1 | F |
| E | 2 | G |
| F | 3 | G |
英文:
- LOOP Op1 over groups ( e.g. A,B,C,... )
- LOOP Op2 over groups starting at Op1 + 1 ( e.g B,C, ... )
- LOOP G over games
- IF neither Op1 nor Op2 has played game G
- ASSIGN Op1 v Op2 in game G
- BREAK from LOOP G

Here is the C++ code

#include &lt;string&gt;
#include &lt;fstream&gt;
#include &lt;sstream&gt;
#include &lt;iostream&gt;
#include &lt;vector&gt;
#include &lt;algorithm&gt;
class cMatchMaker
{
public:
void ParseCommand(int argc, char *argv[])
{
if (argc != 3)
exit(1);
groupCount = atoi(argv[1]);
gameCount = atoi(argv[2]);
}
void ConstructGroups()
{
for (int kg = 0; kg &lt; groupCount; kg++)
{
std::string s({&#39;A&#39; + kg});
vGroup.push_back(s);
vGroupHasPlayed.push_back({});
}
}
void ConstructGames()
{
for (int kg = 0; kg &lt; gameCount; kg++)
{
vGame.push_back(std::to_string(kg + 1));
}
}
void MakeMatches()
{
// loop over groups
for (kop1 = 0; kop1 &lt; groupCount; kop1++)
{
// loop over possible opponents
for (kop2 = kop1 + 1; kop2 &lt; groupCount; kop2++)
{
// loop over games
for (auto &amp;game : vGame)
{
// check neither group has played game
if (!HasGameBeenPlayed(
game))
{
// we have a match!
DisplayMatch(
game);
// remember who played what
Remember(
game);
break;
}
}
}
}
}
private:
int groupCount, gameCount;
std::vector&lt;std::string&gt; vGroup, vGame;
std::vector&lt;std::vector&lt;std::string&gt;&gt; vGroupHasPlayed;
int kop1, kop2;
bool HasGameBeenPlayed(
const std::string &amp;game)
{
if (std::find(
vGroupHasPlayed[kop1].begin(),
vGroupHasPlayed[kop1].end(),
game) != vGroupHasPlayed[kop1].end())
return true;
if (std::find(
vGroupHasPlayed[kop2].begin(),
vGroupHasPlayed[kop2].end(),
game) != vGroupHasPlayed[kop2].end())
return true;
return false;
}
void DisplayMatch(
const std::string &amp;game)
{
std::cout &lt;&lt; &quot; | &quot; &lt;&lt; vGroup[kop1]
&lt;&lt; &quot; | &quot; &lt;&lt; game &lt;&lt; &quot; | &quot;
&lt;&lt; vGroup[kop2] &lt;&lt; &quot; |\n&quot;;
}
void Remember(
const std::string &amp;game)
{
vGroupHasPlayed[kop1].push_back(game);
vGroupHasPlayed[kop2].push_back(game);
}
};
main(int argc, char *argv[])
{
cMatchMaker theMatchMaker;
theMatchMaker.ParseCommand(argc, argv);
theMatchMaker.ConstructGroups();
theMatchMaker.ConstructGames();
theMatchMaker.MakeMatches();
return 0;
}

Here is the output for 7 and 6

Op1 Game Op2
A 1 B
A 2 C
A 3 D
A 4 E
A 5 F
A 6 G
B 3 C
B 2 D
B 5 E
B 4 F
C 1 D
C 6 E
C 4 G
D 6 F
D 5 G
E 1 F
E 2 G
F 3 G

huangapple
  • 本文由 发表于 2023年2月18日 03:22:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/75488480.html
匿名

发表评论

匿名网友

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

确定