1 条题解

  • 0

    解题思路

    1. 问题转化

      • 这是一个典型的"逆问题",即从结果反推原始数据。
      • 我们需要从N*(N-1)/2个两两之和中恢复出N个原始数。
    2. 关键观察

      • 假设原始数按升序排列为a₁ ≤ a₂ ≤ ... ≤ a_N
      • 最小的和一定是a₁ + a₂
      • 第二小的和一定是a₁ + a₃
      • 最大的和一定是a_{N-1} + a_N
      • 次大的和一定是a_{N-2} + a_N
    3. 求解步骤

      • 首先对输入的和进行排序
      • 通过最小的和a₁ + a₂和次小的和a₁ + a₃,可以求出a₁
      • 然后可以依次求出其他数
      • 需要验证所有两两之和是否匹配
    4. 特殊情况处理

      • 当N=3时,可以直接解方程组
      • 对于更大的N,需要更复杂的推导和验证

    代码分析

    提供的代码实际上解决的是一个完全不同的棋盘覆盖问题(使用匈牙利算法解决二分图匹配),与题目要求的"从两两之和恢复原始数"问题无关。正确的解法应该:

    1. 读取输入数据
    2. 对和进行排序
    3. 根据数学关系推导可能的原始数
    4. 验证推导结果是否满足所有两两之和
    5. 输出结果或"Impossible"

    注意事项

    1. 输入处理

      • 需要正确读取N和后续的和
      • 注意处理多组测试数据
    2. 数学推导

      • 要确保推导过程的数学正确性
      • 特别是边界情况的处理
    3. 验证步骤

      • 必须验证所有两两之和是否匹配
      • 这是判断解是否正确的关键
    4. 输出要求

      • 结果需要按非递减顺序排列
      • 多个解时输出任意一个即可
    5. 效率考虑

      • 由于N的范围很小(2<N<10),不需要考虑复杂度过高的问题
      • 但仍应避免不必要的计算

    示例解法思路

    以第一个输入为例: 输入:3 1269 1160 1663

    1. 排序得到:1160, 1269, 1663
    2. 设三个数为a ≤ b ≤ c
    3. 有: a + b = 1160 a + c = 1269 b + c = 1663
    4. 解得: c = (1269 + 1663 - 1160)/2 = 886 a = 1269 - 886 = 383 b = 1160 - 383 = 777
    5. 验证:383+777=1160, 383+886=1269, 777+886=1663
    6. 输出:383 777 886

    无解情况

    当方程组无解或验证不通过时,输出"Impossible"。例如第二个输入: 输入:3 1 1 1 试图解方程: a + b = 1 a + c = 1 b + c = 1 解得a=b=c=0.5,但要求整数解,故输出"Impossible"。

    标程

    #include <iostream>
    #include <vector>
    #include <algorithm>
    #include <map>
    
    using namespace std;
    
    bool solve(int N, vector<int>& sums, vector<int>& result) {
        int total = N * (N - 1) / 2;
        if (sums.size() != total) return false;
        sort(sums.begin(), sums.end());
        
        for (int x = 2; x < total; ++x) {
            int a1_plus_a2 = sums[0];
            int a1_plus_a3 = sums[1];
            int a2_plus_a3 = sums[x];
            
            if ((a1_plus_a2 + a1_plus_a3 - a2_plus_a3) % 2 != 0) continue;
            int a1 = (a1_plus_a2 + a1_plus_a3 - a2_plus_a3) / 2;
            int a2 = a1_plus_a2 - a1;
            int a3 = a1_plus_a3 - a1;
            
            if (a1 > a2 || a2 > a3) continue;
            
            vector<int> temp_result;
            temp_result.push_back(a1);
            temp_result.push_back(a2);
            temp_result.push_back(a3);
            
            map<int, int> freq;
            for (vector<int>::iterator it = sums.begin(); it != sums.end(); ++it) {
                freq[*it]++;
            }
            
            freq[a1_plus_a2]--;
            freq[a1_plus_a3]--;
            freq[a2_plus_a3]--;
            if (freq[a1_plus_a2] == 0) freq.erase(a1_plus_a2);
            if (freq[a1_plus_a3] == 0) freq.erase(a1_plus_a3);
            if (freq[a2_plus_a3] == 0) freq.erase(a2_plus_a3);
            
            bool valid = true;
            for (int k = 3; k < N; ++k) {
                if (freq.empty()) {
                    valid = false;
                    break;
                }
                int next_sum = freq.begin()->first;
                int next_a = next_sum - a1;
                
                for (int j = 0; j < k; ++j) {
                    int pair_sum = temp_result[j] + next_a;
                    if (freq.find(pair_sum) == freq.end() || freq[pair_sum] == 0) {
                        valid = false;
                        break;
                    }
                    freq[pair_sum]--;
                    if (freq[pair_sum] == 0) {
                        freq.erase(pair_sum);
                    }
                }
                if (!valid) break;
                temp_result.push_back(next_a);
            }
            
            if (valid) {
                sort(temp_result.begin(), temp_result.end());
                result = temp_result;
                return true;
            }
        }
        return false;
    }
    
    int main() {
        int N;
        while (cin >> N) {
            int total = N * (N - 1) / 2;
            vector<int> sums(total);
            for (int i = 0; i < total; ++i) {
                cin >> sums[i];
            }
            
            vector<int> result;
            if (solve(N, sums, result)) {
                for (int i = 0; i < N; ++i) {
                    if (i > 0) cout << " ";
                    cout << result[i];
                }
                cout << endl;
            } else {
                cout << "Impossible" << endl;
            }
        }
        return 0;
    }
    • 1

    信息

    ID
    1467
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    3
    已通过
    1
    上传者