The problem is not as difficult as it is seen at first. Carefully examine the structure of the sums will give you the key inspiration.
Let N[0..n] denotes the n numbers and S[0..n*(n-1)/2] denote the pairwise sums. Furthermore, let N and S to be already sorted. We can easily observed that S[0] == N[0] + N[1] and S[1] == N[0] + N[2]. If we've known the value of N[0], then we can know the value of N[1] and N[2]. Then, we remove the sums of N[0..1] and N[2] from S, and the minimum value in S is now the sum of N[0] and N[3]. Thus, N[3] will be known to us, and after remove the sums of N[0..2] and N[3], the minimum value in S will become the sum of N[0] and N[4]. Repeat this procedure, we can calculate out all the values of N.
Now the only problem left to us is how can we know N[0]? If we know the sum of N[1] and N[2], then we can calculate out N[0] with S[0] and S[1] in hand. We known that the sum of N[1] and N[2] must in S, and we can try all these values to get the answer. However, we don't need to try all the values in S. The sum of N[1] and N[2] is no lesser than S[1] == N[0] + N[2], and no greater than the sum of N[1] and N[3]. All possible values in this range include the sums of N[0] and N[i], where 2 < i < n. So we just have to try the first n - 2 + 1 + 1 = n except the first two values of S.
Code:
- /*************************************************************************
- * Copyright (C) 2008 by liukaipeng *
- * liukaipeng at gmail dot com *
- *************************************************************************/
- /* @JUDGE_ID 00000 10202 C++ "Pairsumonious Numbers" */
- #include <algorithm>
- #include <cstdio>
- #include <cstring>
- #include <deque>
- #include <fstream>
- #include <iostream>
- #include <list>
- #include <map>
- #include <queue>
- #include <set>
- #include <stack>
- #include <string>
- #include <vector>
- #include <iterator>
- using namespace std;
- int const maxn = 9;
- bool find_numbers(int *sums, int n, int *numbers)
- {
- int nsums = n*(n-1)/2;
- int mins[maxn]; // all possible values for the minimum number
- int nmins = 0;
- sort(sums, sums + nsums);
- for (int i = 2; i < n && i < nsums; ++i)
- if ((mins[nmins] = sums[0] + sums[1] - sums[i]) % 2 == 0)
- mins[nmins++] /= 2;
- bool found = false;
- for (int m = 0; m < nmins && !found; ++m) {
- numbers[0] = mins[m];
- numbers[1] = sums[0] - mins[m];
- bool used[maxn*(maxn-1)/2] = {true};
- found = true;
- for (int i = 2, j; i < n && found; ++i) {
- for (j = i - 1; j < nsums && used[j]; ++j) {}
- numbers[i] = sums[j] - numbers[0];
- used[j] = true;
- for (int k = 1; k < i && found; ++k) {
- int sum = numbers[i] + numbers[k];
- for (++j; j < nsums && (sums[j] != sum || used[j]); ++j) {}
- if (j != nsums) used[j] = true;
- else found = false;
- }
- }
- }
- return found;
- }
- int main(int argc, char *argv[])
- {
- #ifndef ONLINE_JUDGE
- freopen((string(argv[0]) + ".in").c_str(), "r", stdin);
- freopen((string(argv[0]) + ".out").c_str(), "w", stdout);
- #endif
- for (int n; cin >> n; ) {
- int sums[maxn*(maxn-1)/2];
- for (int i = 0, nsums = n*(n-1)/2; i < nsums; ++i) cin >> sums[i];
- int numbers[maxn];
- if (find_numbers(sums, n, numbers))
- for (int i = 0; i < n; ++i) cout << (i > 0 ? " " : "") << numbers[i];
- else
- cout << "Impossible";
- cout << '/n';
- }
- return 0;
- }