POJ2549-Sumsets【折半搜索】

原题链接
Sumsets
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 10698 Accepted: 2919
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
Source

Waterloo local 2001.06.02
题意:就是从一个数的集合中选出来4个元素满足a+b+c=d,求出最大的d,若是列举的话那么其复杂度会有n4这么多,那么肯定超时,所以我们想到可不可以列举三个数的和,但是这也是不可行的,因为10003太大了,而且不能存储,怎么办呢,将上面的方程进行变形得到a+b=d-c,所以我们可以来枚举a+b和d-c,d从大到小开始枚举,自然这样d就是最大的了,这样算下来复杂度才是n2log(n2)

//http://poj.org/problem?id=2549
#include <algorithm>
#include <iostream>
#include <utility>
#include <sstream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <map>
#include <set>
using namespace std;

typedef long long ll;
const int MOD = int(1e9) + 7;
//int MOD = 99990001;
const int INF = 0x3f3f3f3f;
const ll INFF = (~(0ULL)>>1);
const double EPS = 1e-9;
const double OO = 1e20;
const double PI = acos(-1.0); //M_PI;
const int fx[] = {-1, 1, 0, 0};
const int fy[] = {0, 0, -1, 1};
const int maxn=1000 + 5;
//a+b+c=d;
int n;
ll a[maxn];
struct node
{
	ll val;//代表a+b的值
	int loc1,loc2;//代表a与b的下标
}res[maxn*maxn];//l代表的是所有的a+b的值
bool _find(int l,int r,int d,int c,ll sum){
	while(r-l>1){
		int mid=(l+r)/2;
		if(res[mid].val>=sum) r=mid;
		else l=mid;
	}
	if(res[r].val!=sum) return false;
	else{
		if(d==res[r].loc1||d==res[r].loc2||c==res[r].loc1||c==res[r].loc2) return false;
		else return true;
	}
}
bool cmp(node x,node y){
	return x.val < y.val;
}
int main(){
		while(scanf("%d",&n)==1 && n){
			for(int i=0;i<n;i++)
				scanf("%lld",&a[i]);
			sort(a,a+n);
			int len=0;
			for(int i=0;i<n-1;i++){
				for(int j=i+1;j<n;j++){
					res[len].loc1=i;res[len].loc2=j;
					res[len++].val=a[i]+a[j];
				}
			}
			sort(res,res+len,cmp);
			res[len++].val=INFF;
			for(int d=n-1;d>0;d--){
				for(int c=d-1;c>=0;c--){
					if(_find(-1,len,d,c,a[d] - a[c])){
						printf("%lld\n",a[d]);
						goto END;
					}
				}
			}
			printf("no solution\n");
			END:;
		}
        return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

门豪杰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值