Huawei OD Computer-Based Test Algorithm Questions: Basketball Game

Table of contents

Question part

Interpretation and analysis

Code


Question part

topic Basketball game
difficulty Disaster
Question description In a basketball (5V5) game, each player has a combat effectiveness, and the sum of the combat effectiveness of all players in each team is the overall combat effectiveness of the team. There are currently 10 players ready to be divided into two teams for a training match. The coach hopes that the difference in combat effectiveness between the two teams can be as small as possible to achieve the best training effect. Given the combat effectiveness of 10 players, if you are a coach, how should you divide the teams to achieve the best training effect? ​​Please tell us the minimum combat effectiveness difference under the team plan.
Enter description The combat effectiveness of 10 basketball players (integer, range [1, 10000]) is separated by spaces, such as: 10 9 8 7 6 5 4 3 2 1.
There is no need to consider abnormal input scenarios.
Output description The output describes the minimum combat effectiveness difference, such as: 1.
Additional information none
------------------------------------------------------
Example
Example 1
enter 10 9 8 7 6 5 4 3 2 1
output 1
illustrate 1, 2, 5, 9, and 10 are divided into one team, and 3, 4, 6, 7, and 8 are divided into one team. The difference in combat power between the two teams is the smallest, and the output difference is 1. Note: The player division scheme is not unique, but the minimum combat effectiveness difference is fixed at 1.


Interpretation and analysis

Question interpretation :

The 10 numbers are divided into two groups, each group contains 5 numbers, so that the difference between the sum of the two groups of numbers is minimized. Please output the minimum difference. 

Analysis and ideas :

This question is similar to " Huawei OD computer-based test algorithm questions: Battle for MVP ". They group numbers and require the grouped numbers to meet certain requirements. The difference is that in "MVP Battle", the number of numbers in each group is variable, but in this question, the number of numbers in each group is fixed, all 5. Relatively speaking, the idea and implementation of this question are simpler.

From the 10 numbers, exhaust all situations, calculate the difference between the two teams in each situation, and find the one with the smallest difference.

Assume that these two groups are group A and group B respectively, and these 10 numbers are T_{1}, T_{2}... T_{10}.
Our exhaustive order is to first put them  T_{1} into group A, and then use the same method based on the remaining 9 numbers to exhaust all possible situations where 4 out of 9 numbers can be obtained. In this way, the dimensionality of picking 5 out of 10 numbers is reduced to 4 out of 9 numbers. In the same way, it can finally be reduced to 1 out of 6 numbers.
The above is  T_{1}  the situation of putting it into group A. The next step is to  T_{2} put it into group A, and then from  T_{3} these  T_{10} 8 numbers, exhaust all possible situations of getting 4 numbers out of 8 numbers.

Each time it traverses a situation, when calculating the difference between the two sets of numbers (set as diff), if diff is smaller than the minimum difference calculated during the previous traversal (set as minDiff), then update the value of minDiff. After traversing all situations, the final minDiff value is the output required by the question. The number of iterations of this algorithm is  C_{10}^{5}.

In the above traversal algorithm, there are repeated calculations. The question only cares about the difference between the two groups, so in any combination, exchanging the numbers in group A and the numbers in group B can be regarded as the same situation. For example  T_{1}, putting T_{2}, T_{3}, T_{4}, , T_{5} into group A   is actually equivalent to putting T_{6}, T_{7}, T_{8}, T_{9}, into group A. T_{10}In order to reduce duplication, we can assume that the sum of the numbers in group A is less than or equal to the sum of the numbers in group B, that is, the sum of the numbers in group A is less than or equal to half of the sum of all numbers (set as sum). Then when exhaustively enumerating all situations, it is found that the sum of the numbers in group A has exceeded (sum/2), then this combination can be ignored. This reduces the traversal by half and the number of traversals becomes \frac{C_{10}^{5}}{2}.

Since we need to ensure that the sum of the numbers in group A is less than or equal to (sum/2), we can first sort the numbers from small to large to further reduce the number of traversals.

In summary, the number of iterations of this algorithm does not exceed  \frac{C_{10}^{5}}{2}. Next, we calculate the maximum number of traversals.

From the combined calculation formula  C_{m}^{n} = \frac{m!}{n!(m-n)!}, we can get   \frac{C_{10}^{5}}{2} =  \frac{ 10!}{(5!)(5!)*2} = 126, no more than 126 times at most.


Code

Java code

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;

/**
 * 篮球比赛
 * @since 2023.09.15
 * @version 0.1
 * @author Frank
 *
 */
public class BasketballGame {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		while (sc.hasNext()) {
			String input = sc.nextLine();
			String[] strNumbers = input.split( " " );
			// 此处 count == numbers.count,可以完全不用考虑 count.
			processBasketballGame( strNumbers );
		}
	}
	
	private static void processBasketballGame( String strNumbers[] )
	{
		Integer[] numbers = new Integer[strNumbers.length];
		int sum = 0;
		for( int i = 0; i < numbers.length; i ++ )
		{
			numbers[i] = Integer.parseInt( strNumbers[i] );
			sum += numbers[i];
		}
		
		Arrays.sort( numbers );
		int minDiff = sum;	// minDiff 一定小于 sum
 		
		List<Integer> numList = new ArrayList<Integer>( Arrays.asList( numbers ) );
		
		minDiff = getMinDiff( sum, minDiff, 0, 0, numList );
		System.out.println( minDiff );
	}

	
	private static int getMinDiff( int SUM, int minDiff, int currentSum, int currentCnt, List<Integer> numbers )
	{			
		if( currentCnt + numbers.size() < 5 )
		{
			return SUM;
		}
		
		List<Integer> tmpRemovedNumber = new ArrayList<Integer>(); 
		
		for( int i = 0; i < numbers.size(); i ++ )
		{
			int tmpMinDiff = SUM;
			int tmpNumber = numbers.get( i );
			
			int tmpCurrentSum = currentSum + tmpNumber;
			int tmpCurrentCnt = currentCnt + 1;
			
			if( tmpCurrentSum * 2 > SUM )
			{
				break; // 可以break,因为后面的数字更大。
			}
				
			if( tmpCurrentCnt == 5 )
			{
				tmpMinDiff = SUM - tmpCurrentSum * 2;
				if( tmpMinDiff < minDiff )
				{
					minDiff = tmpMinDiff;
					continue;
				}
			}
			
			tmpRemovedNumber.add( tmpNumber );
			numbers.remove( i );
			tmpMinDiff = getMinDiff( SUM, minDiff, tmpCurrentSum, tmpCurrentCnt, numbers );
			if( tmpMinDiff < minDiff )
			{
				minDiff = tmpMinDiff;
			}
//			numbers.add( i, tmpNumber );  // 不必加回去,可以减少一半的穷举数
		}		
		
		for( int i = 0; i < tmpRemovedNumber.size(); i ++ )
		{
			numbers.add( i, tmpRemovedNumber.get( i ) );
		}
		return minDiff;
	}
	
}

JavaScript code

const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;
void async function() {
    while (line = await readline()) {
        // count 可以忽略
        var strNumbers = line.split(" ");
        processBasketballGame(strNumbers);
    }
}();

function processBasketballGame(strNumbers) {
    var numbers = new Array();
    var sum = 0;
    for (var i = 0; i < strNumbers.length; i++) {
        numbers[i] = parseInt(strNumbers[i]);
        sum += numbers[i];
    }

    numbers.sort();
    var minDiff = sum; // minDiff 一定小于 sum

    minDiff = getMinDiff(sum, minDiff, 0, 0, numbers);
    console.log(minDiff);
}

function getMinDiff(SUM, minDiff, currentSum, currentCnt, numbers) {
    if (currentCnt + numbers.length < 5) {
        return SUM;
    }

    var tmpRemovedNumber = new Array();

    for (var i = 0; i < numbers.length; i++) {
        var tmpMinDiff = SUM;
        var tmpNumber = numbers[i];

        var tmpCurrentSum = currentSum + tmpNumber;
        var tmpCurrentCnt = currentCnt + 1;

        if (tmpCurrentSum * 2 > SUM) {
            break; // 可以break,因为后面的数字更大。
        }

        if (tmpCurrentCnt == 5) {
            tmpMinDiff = SUM - tmpCurrentSum * 2;
            if (tmpMinDiff < minDiff) {
                minDiff = tmpMinDiff;
                continue;
            }
        }

        tmpRemovedNumber.push(tmpNumber);
        numbers.splice(i, 1);
        tmpMinDiff = getMinDiff(SUM, minDiff, tmpCurrentSum, tmpCurrentCnt, numbers);
        if (tmpMinDiff < minDiff) {
            minDiff = tmpMinDiff;
        }
    }

    for (var i = 0; i < tmpRemovedNumber.length; i++) {
        numbers.splice(i, 0, tmpRemovedNumber[i]);
    }
    return minDiff;
}

(over)

Guess you like

Origin blog.csdn.net/ZiJinShi/article/details/132901418