Title: There are n individuals divided into two groups, the difference between the two groups can not exceed 1, find the two groups of people the minimum weight difference.
Analysis: DP, State compression 01 backpack. zoj1880 upgrade version.
First, consider a two-dimensional backpack.
Since it must be placed in a group of two groups, the direct backpack all can go to the state, remove the difference of not more than 1 of the nearest SUM/2 value can be.
Then, optimize.
If the two-dimensional backpack is used directly, due to the large number of data groups will tle, here the use of state-compressed one-dimensional backpack;
Status: F (i) means all possible persons at the time of the total weight of I, the value of f (i), the number on the K-position is 1 represents a combination of K-people.
Transfer: F (i) = f (i) | (f (i-w[j]) << 1), equal to the number of States that can be updated to this state the combination of 1 and the original set.
Finally, scan.
Start scanning down from SUM/2 to find the first solution that satisfies test instructions.
Note: Be aware of the situation of entering 0 persons.
#include <stdio.h> #include <stdlib.h> #include <string.h> long long f[23001];int h[101];int gcd (int A, int b) {return a%b?gcd (b, a%b): b;} int main () {int t,n,sum,r; while (scanf ("%d", &t)! = EOF) while (T--) {scanf ("%d", &n); sum = 0; for (int i = 1; I <= n; + + i) {scanf ("%d", &h[i]); Sum + = H[i]; }//wing volume optimization r = 1; if (n > 0) {r = h[1]; for (int i = 2; I <= n; + + i) R = gcd (r, H[i]); Sum/= R; for (int i = 1; I <= n; + + i) h[i]/= R;} for (int i = SUM/2; I >= 0;--i) f[i] = 0LL; F[0] = 1LL; for (int i = 1; I <= n; + + i) for (int j = SUM/2; J >= H[i];--j) F[j] |= f[j-h[i]]<<1 ; int move = sum/2+1; while (move--) {if (n%2 = = 0 && f[move]& (1ll<< ((n+1)/2)) break; if (n%2 = = 1 && F[move]& (1ll<< ((n+0)/2)) break; if (n%2 = = 1 && f[move]& (1ll<< ((n+1)/2)) break;} printf ("%d%d\n", Move*r, (Sum-move) *r); if (t) printf ("\ n"); } return 0;}
UVa 10032-tug of War