Sumsets

                                                                                                                                                   Sumsets
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 11046   Accepted: 3024

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

5
2 
3 
5 
7 
12
5
2 
16 
64 
256 
1024
0

Sample Output

12
no solution

题意:给定n个数组成一个集合S,从S中找到一个数d以及a,b,c,使得d=a+b+c,现在要挑选出最大的d满足上述条件,如果没有找到,输出'no solution'
思路:将等式改为a+b=d-c,对于等式的左右两边,第一步:可以分别枚举出所有可能的情况,第二步:对于等式左边的每一种情况,在等式右边进行二分搜索,搜索出所有和等式左边的和值相等的所有情况,不断的更新d值即可。
需要注意的是集合S中的每个元素不能重复的使用,只能使用一次,所以在第二步中对等式右边搜索出来的情况还需要进行筛选操作,如果等式右边的元素与左边重复了,就需要舍弃这种情况!!
AC代码:
#define _CRT_SECURE_NO_DEPRECATE
#include<iostream>
#include<algorithm>
#include<vector>
#include<functional>
using namespace std;
typedef long long ll;
const int N_MAX = 1000 + 4;
int n;
ll S[N_MAX];
struct Set {
    ll sum;
    int i, j;
    Set(ll s,int a,int b):sum(s),i(a),j(b) {}
    bool operator <(const Set&b)const {
        return sum < b.sum;
    }
    bool operator >(const Set&b)const {//!!!!!!!
        return sum > b.sum;
    }
    bool operator != (const Set&b)const {
        return (i != b.i&&i != b.j&&j != b.j&&j != b.i);//!!!!!
    }
};


int main() {
    
    while (scanf("%d",&n)&&n) {
        for (int i = 0; i < n; i++) {
            scanf("%lld",&S[i]);
        }
        vector<Set>Left;
        vector<Set>Right;
        for (int i = 0; i < n; i++) {
            for (int j = i + 1; j < n; j++) {
                Left.push_back(Set(S[i]+S[j],i,j));
            }
      }
        for (int i = 0; i < n; i++) {
            for (int j = i + 1; j < n; j++) {
                Right.push_back(Set(S[i]-S[j],i,j));
                Right.push_back(Set(S[j] - S[i], j, i));//!!!!!!!!!!!!!两种情况都要算上
            }
        }
        sort(Left.begin(),Left.end());//有序排列再进行二分搜索!!!!!!!!!!!!
        sort(Right.begin(),Right.end());
        ll res=-INT_MAX ;
        for (vector<Set>::const_iterator it = Left.begin(); it != Left.end(); it++) {//对于左侧计算出来的每一个值!!!!!!!!!!!!!!!
            vector<Set>::iterator lb = lower_bound(Right.begin(),Right.end(),*it);//找出右侧与左边和值相等的差
            vector<Set>::iterator ub = upper_bound(lb, Right.end(), *it);/////以lb起始减少查找次数
            for (; lb!=ub;lb++) {
                if (*it != *lb) {//所取得左右两边的元素都不一样!!!!!!!!!!!!!!!!!!!!!1
                    res = max(res, it->sum+S[lb->j]);
                }
             }
        }
        if (res <- 536870912)printf("no solution\n");
        else printf("%lld\n",res);
    }
    return 0;
}

 

posted on 2017-03-09 13:31  ZefengYao  阅读(238)  评论(0)    收藏  举报

导航