// Tug of war (tug-of-war) // PC/Ultraviolet IDs: 110805/10032, popularity: B, success rate: Low Level: 2 // verdict: Online ultraviolet A-Wrong answer, programming-challenges-solved // submission date: 2011-08-09 // programming-challenges run time: 0.020 S // All Rights Reserved (c) 2011, Qiu. Metaphysis # Yeah dot net // directly enumerative subsets are not feasible because the number of given subsets is too large. The solution is as follows: determine the total weight that can be obtained for all subsets. // The total weight of each subset is much less than that of the subset. To obtain all the possible total weights, sort the weights in ascending order. Set the total number of first team members to I, and the total number of second team members to J, the total weight of all personnel is g, and the total number is N. According to the question, // The difference between the two teams cannot exceed one person, so I and j can be determined based on the total number n, if n is an even number, I = J = // [n/2]. If n is an odd number, I = [n/2]. j = [n/2] + 1. the symbol [] indicates an integer. Since we have sorted the weights in ascending order, we can know that the weights of the first I people and the minimum weights that can be obtained, the next J individual's weight // and is the maximum possible weight. The weight of a team may only change within this range. To obtain the weight distribution of the two teams with the smallest difference, you can // compare the weight difference between the former I and the latter J, take the two people who first get the minimum difference, exchange their weight, and determine whether or not to reach half of the total weight. If the difference reaches, return. If it is still less than half of the total weight, sort the weights of the two teams in ascending order, and find two people with the minimum weight difference, until the total weight of the former team reaches or is greater than half of the total weight, obtain a group of values with a small difference in body/weight and weight. This ensures that all possible body values are obtained. When the value is smaller than g/2 and greater than g/2, you need to determine which difference is smaller. //// What is interesting is that the solution obtained by others using the dynamic planning algorithm is obtained from the programming challenges and ultraviolet A. // some test data cannot be passed. I use this algorithm, I passed all the data on the Forum, and some AC programs passed the // wrong data. It can be seen that the test data on PC and ultraviolet A is not very strong. Examples of programs that use dynamic planning to solve problems can be referred to // http://tausiq.wordpress.com/2011/03/07/uva-10032-tug-of-war/, comments containing test data that cannot pass. /// Another question (question 562) on the ultraviolet A is very similar to this question. It is a coin issue, but it is different from this question, there is no limit to the maximum number of coins divided into two parts. More general this type of problem is called the balance Division problem, can use dynamic planning to solve, can // reference: http://people.csail.mit.edu/bdean/6.046/dp. /// This solution is passed on progrmming challenges and WA on the ultraviolet A online judge. # Include <iostream> # include <vector> # include <algorithm> using namespace STD; # define max_diff 450 // maximum possible weight difference between two people. Int tug_of_war (vector <int> & weight, int sum) {// if there is only one person, the weight of a team is obviously 0, the weight of the other team is the weight of the only person who participates in the picnic. If (weight. Size () = 1) return 0; // sort the body values in ascending order to obtain an ascending sequence of the overall values. Sort (weight. begin (), weight. end (); int lower, upper; lower = weight. size ()/2-1; upper = Lower + 1; // search for and replace the first two teams with the least difference in weight among the two teams, when the total weight of the current team is less than that of the latter team, continue the process until the weight of the former team is equal to or greater than half of the total weight. Int origin_lower, origin_upper; while (true) {int memo_lower, memo_upper; int diff_weight = max_diff; // find the two players with the least weight difference among the first players. Bool changed = false; For (INT m = 0; m <= lower; m ++) {for (INT n = upper; n <weight. size (); N ++) {int TMP = weight. at (N)-weight. at (m); // ensure that the weight and weight of the old team are higher than those of the old team. If (TMP> 0 & TMP <diff_weight) {memo_lower = m; memo_upper = N; diff_weight = weight. at (N)-weight. at (m); changed = true ;}}// if found, exchange the two players with the smallest difference. If (changed = true) {origin_lower = weight. at (memo_lower); origin_upper = weight. at (memo_upper); int TMP = weight. at (memo_lower); weight. at (memo_lower) = weight. at (memo_upper); weight. at (memo_upper) = TMP;} // calculate the weights and values of the previous team. Int team_weight = 0; For (INT I = 0; I <= lower; I ++) team_weight + = weight. at (I); // No two players whose difference is greater than 0 are found, or the former team has half of the weight equal to the total weight, returns the current // weight of the previous team and the expected weight for the question. If (changed = false | team_weight = (sum/2) return team_weight; // weight of the former team and half of the total weight, sort the weights of the two teams in ascending order and then replace them. If (team_weight <(sum/2) {sort (weight. begin (), weight. begin () + lower); sort (weight. begin () + upper, weight. end (); continue;} // the weight of the former team is half the total weight of the former team, and the weight difference between the former Replacement team and the current two teams is compared, take a group with a small difference. Int team_a = 0, team_ B = 0; For (INT I = 0; I <= lower; I ++) team_a + = weight. at (I); team_ B = team_a + origin_lower-origin_upper; If (ABS (2 * team_a-sum) <ABS (2 * team_ B-sum) Return (Sum-team_a ); elsereturn team_ B ;}} int main (INT AC, char * AV []) {INT cases; // Number of test data groups. Vector <int> weight; // record the body value. Cin> cases; while (cases --) {int N; // total number of participants in the picnic. Int TMP; // TMP indicates the weight of a single individual. Int sum = 0; // sum indicates the total weight. Weight. clear (); CIN> N; while (n --) {CIN> TMP; sum + = TMP; weight. push_back (TMP);} // obtain the overall values of a team with a smaller weight. Int smaller = tug_of_war (weight, sum); cout <smaller <"" <(Sum-smaller) <Endl; If (cases) cout <Endl ;} return 0 ;}