UVa Problem Solution: 10202 - Pairsumonious Numbers


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:
  1. /*************************************************************************
  2.  * Copyright (C) 2008 by liukaipeng                                      *
  3.  * liukaipeng at gmail dot com                                           *
  4.  *************************************************************************/
  5. /* @JUDGE_ID 00000 10202 C++ "Pairsumonious Numbers" */
  6. #include <algorithm>
  7. #include <cstdio>
  8. #include <cstring>
  9. #include <deque>
  10. #include <fstream>
  11. #include <iostream>
  12. #include <list>
  13. #include <map>
  14. #include <queue>
  15. #include <set>
  16. #include <stack>
  17. #include <string>
  18. #include <vector>
  19. #include <iterator>
  20. using namespace std;
  21.    
  22. int const maxn = 9;
  23.  
  24. bool find_numbers(int *sums, int n, int *numbers) 
  25. {
  26.   int nsums = n*(n-1)/2;
  27.   int mins[maxn]; // all possible values for the minimum number
  28.   int nmins = 0;
  29.   sort(sums, sums + nsums);
  30.   for (int i = 2; i < n && i < nsums; ++i)
  31.     if ((mins[nmins] = sums[0] + sums[1] - sums[i]) % 2 == 0)
  32.       mins[nmins++] /= 2;
  33.   
  34.   bool found = false;
  35.   for (int m = 0; m < nmins && !found; ++m) {
  36.     numbers[0] = mins[m];
  37.     numbers[1] = sums[0] - mins[m];
  38.     bool used[maxn*(maxn-1)/2] = {true};
  39.     found = true;
  40.     for (int i = 2, j; i < n && found; ++i) {
  41.       for (j = i - 1; j < nsums && used[j]; ++j) {}
  42.       numbers[i] = sums[j] - numbers[0];
  43.       used[j] = true;
  44.       for (int k = 1; k < i && found; ++k) {
  45.         int sum = numbers[i] + numbers[k];
  46.         for (++j; j < nsums && (sums[j] != sum || used[j]); ++j) {}
  47.         if (j != nsums) used[j] = true;
  48.         else found = false;
  49.       }
  50.     }
  51.   }
  52.   return found;
  53. }
  54.           
  55. int main(int argc, char *argv[])
  56. {
  57. #ifndef ONLINE_JUDGE
  58.   freopen((string(argv[0]) + ".in").c_str(), "r", stdin);
  59.   freopen((string(argv[0]) + ".out").c_str(), "w", stdout);
  60. #endif
  61.   for (int n; cin >> n; ) {
  62.     int sums[maxn*(maxn-1)/2];
  63.     for (int i = 0, nsums = n*(n-1)/2; i < nsums; ++i) cin >> sums[i];
  64.     int numbers[maxn];
  65.     if (find_numbers(sums, n, numbers))
  66.       for (int i = 0; i < n; ++i) cout << (i > 0 ? " " : "") << numbers[i];
  67.     else
  68.       cout << "Impossible";
  69.     cout << '/n';
  70.   }
  71.   return 0;
  72. }

發佈了69 篇原創文章 · 獲贊 2 · 訪問量 17萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章