最容易想到的办法是枚举四个数,当然肯定会超时。
于是想到一个办法S=a+b+c,三个循环+二分查找S,结果也超时。
然后发挥非凡想象力的时候到了,S-a=b+c,两个循环+二分查找b+c。这样时间复杂度可以大大降低。
可以枚举b+c的和,注意这里会有n*(n+1)/2种情况,所以开数组要大点。另外要考虑到S,a,b,c不能重了,所以用结构体同时把b,c的序号也保存下来。
还有要注意二分查找前要排序。
这里要求最大的S,所以可以先将该集合排序,最后从大到小枚举S和a,出现的第一个符合的S和a就是答案。
#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <algorithm>
using namespace std;
struct Sum_two
{
int a,b;
int val;
};
int BSsearch(Sum_two *A,int low,int high,int key)
{
while(low<high)
{
int mid=(high+low)/2;
if(A[mid].val==key) return mid;
else if(key<A[mid].val) high=mid-1;
else low=mid+1;
}
return -1;
}
bool cmp(Sum_two a,Sum_two b)
{
return a.val<b.val;
}
Sum_two sum[500505];
int main()
{
int n;
while(scanf("%d",&n)&&n)
{
int a[1005]={0},ans=0;
bool p=false;
for(int i=0;i<n;++i)
scanf("%d",&a[i]);
if(n>=4)
{
sort(a,a+n);
int N=0;
for(int i=0;i<n-1;++i)
for(int j=i+1;j<n;++j)
{
sum[N].val=a[i]+a[j];
sum[N].a=i;sum[N].b=j;
N++;
}
sort(sum,sum+N,cmp);
for(int i=n-1;i>=0&&!p;--i)
for(int j=n-1;j>=0&&!p;--j)
{
int key=a[i]-a[j];
int x;
if(i!=j&&(x=BSsearch(sum,0,N,key))!=-1)
{
if(sum[x].a==i||sum[x].b==j) continue;
if(sum[x].a==j||sum[x].b==i) continue;
ans=a[i];
p=true;
}
}
}
if(p) printf("%d\n",ans);
else printf("no solution\n");
}
return 0;
}