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 "); else printf("%lld ",res); } return 0; }