题目大意:
有一个a数组,将它的任意两个元素求一次和,得到的所有值和a数组里原来的所有数全部存到b数组里面,现在给你b数组,让你求出对应的a数组并按照从小到大的顺序输出。
分析:
首先把b数组从小到大排序处理,之后,b数组里最小的两个一定是a数组里的数,取出这两个数 b[1]、b[2] 然后删除 a[1]+a[2],再取出 b 中当前最小的,即为 a[3] ,在删除a[1] + a[3]、a[2]+a[3] …… 以此类推,直到取出了 b 中的所有 a 。关于如何删除,我选择用优先队列存储当前已经确定的所有 a 两两组合所能产生的所有 b ,在每一次要取最小值的时候,判断当前b的值是否等于队首,如果等于就删除队首,并且寻找下一个。
代码:
#include<bits/stdc++.h>
using namespace std;
struct cmp1{
bool operator ()(int &a,int &b){
return a>b;//最小值优先
}
};
int a[1000];
int b[200000];
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
for(int i=0;i<n;i++)
{
scanf("%d",&b[i]);
}
if(n==0)
{
printf("0\n");
continue;
}
if(n==1)
{
printf("1\n%d\n",b[0]);
continue;
}
sort(b,b+n);
priority_queue<int,vector<int>,cmp1>q;
a[0]=b[0];
a[1]=b[1];
q.push(a[0]+a[1]);
int num=2;
for(int i=2;i<n;i++)
{
if(q.empty()==1||b[i]!=q.top())
{
a[num]=b[i];
for(int j=0;j<num;j++)
{
q.push(a[num]+a[j]);
//cout<<"push"<<a[num]+a[j]<<endl;
}
num++;
}
else
{
//cout<<"pop:"<<b[i]<<endl;;
q.pop();
}
}
printf("%d\n",num);
printf("%d",a[0]);
for(int i=1;i<num;i++)
{
printf(" %d",a[i]);
}
printf("\n");
}
}