POJ2549_Sumsets_

来源:互联网 发布:淘宝怎么1元秒杀 编辑:程序博客网 时间:2024/06/05 02:17

Sumsets
Time Limit: 1000MS Memory Limit: 65536KTotal Submissions: 11294 Accepted: 3101

Description

Given S, a set of integers, find the largest d such that a + b + c = d where a, b, c, and d are distinct elements of S.

Input

Several S, each consisting of a line containing an integer 1 <= n <= 1000 indicating the number of elements in S, followed by the elements of S, one per line. Each element of S is a distinct integer between -536870912 and +536870911 inclusive. The last line of input contains 0.

Output

For each S, a single line containing d, or a single line containing "no solution".

Sample Input

52 3 5 7 1252 16 64 256 10240

Sample Output

12no solution

Source

给定一个含有 N 个元素的集合,从集合中选取 a,b,c,d 四个元素,使 a+b+c=d 成立。求最大的d。


显然是一个折半枚举的题。N <= 1000 , 直接枚举 O(n4) 复杂度太高。采用折半枚举的思想,两个两个的枚举。

先枚举两个数的和,再枚举两个数的差。然后用二分搜索把两个值匹配起来,注意元素不能重复利用就好了。


#include<cstdio>#include<iostream>#include<algorithm>using namespace std;typedef long long LL;struct P{LL s, x, y;P(){};P(LL a, LL b, LL c):s(a), x(b), y(c){};bool operator < (P k){return s < k.s;}};const LL inf = 6000000000;const int maxn = 1000 + 10;LL S[maxn];P sum[maxn * maxn];int N;bool cmp(LL x, LL y){return x > y;}int main (){while(1){cin >> N;if(N == 0) break;for(int i= 0; i< N; i++)scanf("%lld", S+i);sort(S, S+N, cmp);//将 S 从大到小排序//枚举连个数的和int cnt = 0;for(int i= 0; i< N; i++)for(int j= i+1; j< N; j++){sum[cnt].x = S[i]; //加数sum[cnt].y = S[j]; //加数sum[cnt].s = S[i] + S[j];//和cnt ++;}sort(sum, sum+cnt);//将 sum 从小到大排序//枚举两个数的差LL ans = -inf;for(int i= 0; i< N; i++)for(int j= 0; j< N; j++){if(i == j) continue;//二分搜索匹配P temp (S[i]-S[j], -inf, -inf);int pos = lower_bound(sum, sum+cnt, temp) - sum;for(int k= pos; k<cnt && sum[k].s == S[i]-S[j]; k++){//去重if(sum[k].x != S[i] && sum[k].x != S[j]&& sum[k].y != S[i] && sum[k].y != S[j]){ans = max(ans, S[i]);}}}if(ans == -inf) cout << "no solution\n";else cout << ans << endl;}return 0;}