Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 如何根据一个变量将一个集合平衡为多个其他集合?_Algorithm - Fatal编程技术网

Algorithm 如何根据一个变量将一个集合平衡为多个其他集合?

Algorithm 如何根据一个变量将一个集合平衡为多个其他集合?,algorithm,Algorithm,基本上,我一共有20个玩家,每个玩家有2个属性 { "name": "John Doe", "goals": 20 } 我试图完成的是将球员名单和他们的目标输入到一个算法中,该算法将球队平均分为两支球队,但要基于他们的目标,并以尽可能小的差异来平衡球队。玩家的数量总是可以被2整除,所以这不是问题 例如,假设我们在一个数组/集合中有4个玩家(为了简洁起见) “无名氏”-5个进球 “无名氏”-1球 “詹姆斯·多伊”-3个进球 “马克·多伊”-7个进球 经过该算法后,将产生两个单独的

基本上,我一共有20个玩家,每个玩家有2个属性

{
    "name": "John Doe",
    "goals": 20
}
我试图完成的是将球员名单和他们的目标输入到一个算法中,该算法将球队平均分为两支球队,但要基于他们的目标,并以尽可能小的差异来平衡球队。玩家的数量总是可以被2整除,所以这不是问题

例如,假设我们在一个数组/集合中有4个玩家(为了简洁起见)

  • “无名氏”-5个进球
  • “无名氏”-1球
  • “詹姆斯·多伊”-3个进球
  • “马克·多伊”-7个进球
  • 经过该算法后,将产生两个单独的数组/集合,如下所示

    |    Team 1     |    Team 2     |
    |---------------|---------------|
    | John Doe      | Jane Doe      |
    | James Doe     | Mark Doe      |
    |               |               |
    | Avg: 4 Goals  | Avg: 4 Goals  |
    |               |               |
    | Goal Total: 8 | Goal Total: 8 |
    

    显然,有时两队并不完全平等,但理想情况下,我希望在这些情况下尽可能接近。例如,假设团队1有8个目标,团队2有7个目标。

    我之前在评论中提到过贪婪的解决方案(在对输入进行排序后)会起作用。但是正如
    @Prune
    和其他人所指出的,贪婪的解决方案在这里不起作用,而是需要一个动态规划解决方案。以下是我的实现is
    C++

    #include <iostream>
    #include <algorithm>
    #include <vector>
    #include <string>
    #include <numeric>
    #include <sstream>
    #include <fstream>
    
    class Pair{
        public:
            int difference;
            std::vector <int> solution;
    
            Pair(){
                difference = -1;
                solution.clear();
            }
    
            Pair(int d, std::vector <int> v) : difference(d), solution(v){}
    
            bool operator < (const Pair &p) const{
                return difference < p.difference;
            }
    };
    
    class Player{
        public:
            std::string name;
            int goals;
    
            Player() = default;
            Player(std::string n, int g) : name(n), goals(g) {}
    
            friend std::ostream& operator << (std::ostream& out, const Player &player);
    };
    
    std::ostream& operator << (std::ostream& out, const Player &player){
        out << "Player Name: " << player.name << " Player Goals: " << player.goals;
        return out;
    }
    
    constexpr int MAX_PLAYER = 6;
    constexpr int MAX_GOAL = 101;
    constexpr int INF = 1e9;
    
    Pair dp[MAX_PLAYER + 5][MAX_GOAL + 5];
    
    Pair partition(std::vector <Player> players, int index, int val, std::vector <int> result, int sum){
        if(index == players.size() || result.size() == (players.size() / 2)){
            int oppostion = sum - val;
            if(result.size() == players.size() / 2) return Pair(std::abs(val - oppostion), result); 
            return Pair(INF, std::vector <int>()); // return a high difference + empty vector
        }
    
        if(dp[index][val].difference != -1) {
            return dp[index][val];
        }
    
        Pair ret1 = partition(players, index + 1, val,  result, sum);
        result.push_back(index);
        Pair ret2 = partition(players, index + 1, val + players[index].goals, result, sum);
        //std::cout << " index " << index << " val " << val << "\n";
    
        return dp[index][val] = (ret1 < ret2 ? ret1 : ret2);
    }
    
    std::vector <Player> readInput(std::ifstream &ifs){
        std::vector <Player> players;
        std::string inputLine;
        while(std::getline(ifs, inputLine)){
            std::istringstream iss(inputLine);
            std::string name;
            int goals;
            iss >> name >> goals;
            players.emplace_back(name, goals);
        }
        return players;
    }
    
    auto accumulate_func = [](int accumulator, const Player& player){
       return accumulator + player.goals;
    };
    
    int main(int argc, char const *argv[])
    {
        //freopen("out.txt", "w", stdout);
        std::ifstream ifs("in.txt");
        std::vector <Player> players = readInput(ifs);
    
        int sumGoals = std::accumulate(players.begin(), players.end(), 0, accumulate_func);
    
        std::cout << "Total Goals: " << sumGoals << "\n";
    
        Pair ret = partition(players, 0, 0, std::vector <int> (), sumGoals);
        std::cout << "Optimal goal difference " << ret.difference << '\n';
    
        std::vector <Player> teamA;
        std::vector <Player> teamB;
    
        std::vector <int> teamAIndices;
    
        for(int index : ret.solution){
            teamAIndices.push_back(index);
            teamA.push_back(players[index]);
        }
    
        for(int i = 0, k = 0 ; i < players.size() ; ++i){
            if(i == teamAIndices[k]){
                // this player has already been considered
                k++;
            } else{
                teamB.push_back(players[i]);
            }
        }
    
    
        std::cout << "-----Team A-----\n";
        for(const Player &player : teamA){
            std::cout << player << "\n";
        }
    
        std::cout << "\n";
    
        std::cout << "-----Team B-----\n";
        for(const Player &player : teamB){
            std::cout << player << "\n";
        }
    
        int goalsTeamA = std::accumulate(teamA.begin(), teamA.end(), 0, accumulate_func);
        int goalsTeamB = std::accumulate(teamB.begin(), teamB.end(), 0, accumulate_func);
    
        std::cout << "\nGoals of Team A: " << goalsTeamA << " Goals of Team B: " << goalsTeamB << "\n";
        std::cout << "Average goals of Team A: " << goalsTeamA / static_cast <double> (teamA.size()) << " Average goals of Team B: " << goalsTeamB / static_cast <double> (teamB.size()) << "\n";
    
        return 0;
    }
    
    输出:

    Total Goals: 101
    Optimal goal difference 1
    -----Team A-----
    Player Name: John_Doe Player Goals: 10
    Player Name: X_Doe Player Goals: 9
    Player Name: Y_Doe Player Goals: 31
    Player Name: A_Doe Player Goals: 1
    
    -----Team B-----
    Player Name: Jane_Doe Player Goals: 15
    Player Name: James_Doe Player Goals: 7
    Player Name: Mark_Doe Player Goals: 25
    Player Name: Z_Doe Player Goals: 3
    
    Goals of Team A: 51 Goals of Team B: 50
    Average goals of Team A: 12.75 Average goals of Team B: 12.5
    
    Total Goals: 68
    Optimal goal difference 0
    -----Team A-----
    Player Name: Jane_Doe Player Goals: 12
    Player Name: James_Doe Player Goals: 10
    Player Name: Mark_Doe Player Goals: 8
    Player Name: Z_Doe Player Goals: 4
    
    -----Team B-----
    Player Name: John_Doe Player Goals: 20
    Player Name: X_Doe Player Goals: 6
    Player Name: Y_Doe Player Goals: 5
    Player Name: A_Doe Player Goals: 3
    
    Goals of Team A: 34 Goals of Team B: 34
    Average goals of Team A: 8.5 Average goals of Team B: 8.5
    
    我在玩家的名字和姓氏之间加了一个下划线,因为我不太想处理输入解析(由空格分隔的名称部分的可变数量…)。您只需用空格替换

    对于文章中提到的输入,它给出了:

    Total Goals: 16
    Optimal goal difference 0
    -----Team A-----
    Player Name: John_Doe Player Goals: 5
    Player Name: James_Doe Player Goals: 3
    
    -----Team B-----
    Player Name: Jane_Doe Player Goals: 1
    Player Name: Mark_Doe Player Goals: 7
    
    Goals of Team A: 8 Goals of Team B: 8
    Average goals of Team A: 4 Average goals of Team B: 4
    
    注释中
    @Prune
    给出的输入:

    John_Doe 20
    Jane_Doe 12
    James_Doe 10
    Mark_Doe 8
    X_Doe 6
    Y_Doe 5
    Z_Doe 4
    A_Doe 3
    
    输出:

    Total Goals: 101
    Optimal goal difference 1
    -----Team A-----
    Player Name: John_Doe Player Goals: 10
    Player Name: X_Doe Player Goals: 9
    Player Name: Y_Doe Player Goals: 31
    Player Name: A_Doe Player Goals: 1
    
    -----Team B-----
    Player Name: Jane_Doe Player Goals: 15
    Player Name: James_Doe Player Goals: 7
    Player Name: Mark_Doe Player Goals: 25
    Player Name: Z_Doe Player Goals: 3
    
    Goals of Team A: 51 Goals of Team B: 50
    Average goals of Team A: 12.75 Average goals of Team B: 12.5
    
    Total Goals: 68
    Optimal goal difference 0
    -----Team A-----
    Player Name: Jane_Doe Player Goals: 12
    Player Name: James_Doe Player Goals: 10
    Player Name: Mark_Doe Player Goals: 8
    Player Name: Z_Doe Player Goals: 4
    
    -----Team B-----
    Player Name: John_Doe Player Goals: 20
    Player Name: X_Doe Player Goals: 6
    Player Name: Y_Doe Player Goals: 5
    Player Name: A_Doe Player Goals: 3
    
    Goals of Team A: 34 Goals of Team B: 34
    Average goals of Team A: 8.5 Average goals of Team B: 8.5
    

    根据输入更改
    MAX\u玩家
    MAX\u目标

    首先根据球员的目标对球员进行排序,然后从前面挑选一名球员,从后面挑选另一名球员,将他们配对,然后将他们放在一个团队中如何?例如,假设在对目标进行排序后,
    15,11,9,6
    ,那么
    15
    &
    6
    将在一个团队中,而
    11
    &
    9
    将在另一个团队中。配对时只需在1队和2队之间切换。@Robur_131您是否可以详细说明一下“配对时在1队和2队之间切换”的含义?您是否也可以提供一些伪代码来帮助我更好地理解您的解释问得好。现在我的建议如下1。动态规划:背包算法2。使用这个简单的方法:将数组分成两个相等的子元素,其总和几乎相同?@Robur_131:这种切换假设分布具有一定的均匀性。考虑一个池,它具有更典型的倾斜分布,如<代码>(20, 12, 10,8, 6, 5,4, 3)< /代码>。配对在这里完全失败,即使是1-2-2。。。备选方案:
    [20,8,5,4]
    仍然是不正确的解决方案。您需要一种能够将
    [20,6,5,3]
    识别为可接受的算法。