这道题比较关键的地方有两个,一个是怎么求出前三个数,再就是怎么计算后面的数。枚举法真的是很好的辅助方法,当不能准确确定的时候,都可以考虑一下枚举法。如果都是正整数的话,可以通过和的大小关系来减少枚举量,否则就老实枚举吧。求后面的数时注意k_i一定是a_1 - a_w 中得最小数和a_w+1 - a_n中得最小数相加得到的,每次算出一个数,要把已知的和去掉。
实现的时候注意,每次枚举都要把标记数组清零。还有就是当在去掉和时发现了不存在的,一定是当前枚举的不符合条件,直接continue。
#include <cstdio>
#include <string.h>
#include <stdlib.h>
using namespace std;
int n, a[15], k[120];
bool vis[120];
int compare(const void* a, const void* b){
return (*(int *)a - *(int*)b);
}
int main(){
while(~scanf("%d", &n)){
int N = n*(n-1)/2;
for(int i=1;i<=N;i++)
scanf("%d", &k[i]);
qsort(k+1, N, sizeof(int), compare);
bool flag = 0;
for(int i=3;i<=N;i++){
int tp1, tp2, tp3, tpsum = k[1]+k[2];
memset(vis, 0, sizeof(vis));
tpsum += k[i];
if(tpsum%2 != 0) continue;
tpsum /= 2;
tp1 = tpsum - k[i];
tp2 = tpsum - k[2];
tp3 = tpsum - k[1];
a[1] = tp1;a[2] = tp2;a[3] = tp3;
vis[1] = vis[2] = vis[i] = 1;
int j = 3;
bool istrue = 1;
for(int cu=4;cu<=n;cu++){
while(vis[j]){j++;}
vis[j] = 1;
a[cu] = k[j++] - a[1];
int t = j;
for(int l=2;l<cu;l++){
for(;(k[t]!=a[l]+a[cu]||vis[t])&&t<=N;t++);
if(t>N){istrue = 0;break;}
vis[t] = 1;
}
if(!istrue)
break;
}
if(!istrue) continue;
flag = 1;
printf("%d", a[1]);
for(int l=2;l<=n;l++)
printf(" %d", a[l]);
printf("\n");
break;
}
if(!flag)
printf("Impossible\n");
}
return 0;
}