代码里有注释 QAQ
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 22;
int n, num, a[N * N];
int res[N];
bool vis[N][N]; /// vis[i][j] 表示 res[i] + res[j] 是否已经算过
bool check()
{
/// 考虑只有 4 个元素,当 j = 3,a[3] = a + d 或 b + c
/// 当 a[3] == b + c,令 a[3] 就等于 b + c
/// 后三项一定为 d + (a / b / c),如果不相同,舍
/// 否则,令 a[3] = a + d,求出 d,继续计算
/// 此时下一项一定为 b + c,如果 a[4] != b + c,舍
/// 如果 a[4] == b + c,a[5] = b + d,a[6] = c + d
/// 不断看后一项,要么为之前求出的两个元素之和,要么新增一个元素,
/// 当所有元素都已经求出,然而剩下的 a[] 中没有元素 = 已知两个元素的和,return false;
int cnt = 2; /// 之前已经求出几个元素
int pos = 1; /// 之前搞定了 a[1] - a[pos]
while (pos < num)
{
bool flag = false; /// 能否由之前两个未使用的数相加得到
pos++;
for (int i = 1; i <= cnt; i++)
{
for (int j = i + 1; j <= cnt; j++)
if ((!vis[i][j]) && res[i] + res[j] == a[pos]) {
flag = true; vis[i][j] = true; break;
}
if (flag) break;
}
/// 从最小的数开始
if (!flag) res[++cnt] = a[pos] - res[1];
/// 无法再多制造一个元素 res[++cnt] = a[pos] - res[1]
if (cnt == n + 1) return false;
}
return true;
}
int main()
{
while (scanf("%d", &n) != EOF)
{
if (n == 2) { printf("Impossible\n"); continue; }
num = n * (n - 1) / 2;
for (int i = 1; i <= num; i++) scanf("%d", &a[i]);
sort(a + 1, a + num + 1);
bool key = false;
for (int i = 0; i <= a[1] / 2; i++) /// 枚举 a,求出 b,res[3] 不确定
{
memset(vis, 0, sizeof(vis));
res[1] = i; res[2] = a[1] - res[1]; vis[1][2] = true;
if (check()) {
for (int i = 1; i <= n; i++) printf("%d ", res[i]);
printf("\n");
key = true; break;
}
}
if (!key) printf("Impossible\n");
}
return 0;
}