POJ 2549 折半枚举 / 3SUM

题意

传送门 POJ 2549

折半枚举

枚举 a + b a+b 排序之,枚举 d c d-c 二分求满足 a + b + c = d a+b+c=d 且元素不重复的最大 d d ,复杂度 O ( n 2 l o g n ) O(n^2logn)

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define min(a,b)    (((a) < (b)) ? (a) : (b))
#define max(a,b)    (((a) > (b)) ? (a) : (b))
#define abs(x)    ((x) < 0 ? -(x) : (x))
#define INF 0x7fffffff
#define delta 0.85
#define eps 1e-5
#define PI 3.14159265358979323846
#define MAX_N 1000
using namespace std;
typedef pair<int, int> P;
int N, sz, res;
int S[MAX_N];
P H[(MAX_N - 1) * MAX_N / 2];

bool update(int x, int y){
	bool flag = 0;
	int s = x - y;
	for(P *p = lower_bound(H, H + sz, P(s, -INF)); p != upper_bound(H, H + sz, P(s, INF)); p++){
		int s2 = p->first, z = p->second;
		// 判断元素重复
		if(x == z || x == s2 - z || y == z || y == s2 - z) continue;
		if(!flag || res < x) flag = 1, res = x;
	}
	return flag;
}

int main(){
	while(~scanf("%d", &N) && N){
		for(int i = 0; i < N; i++) scanf("%d", S + i);
		// 从较大值向下搜索,可以尽快结束搜索
		sort(S, S + N);
		sz = 0;
		for(int i = 0; i < N; i++){
			for(int j = i + 1; j < N; j++){
				H[sz++] = P(S[i] + S[j], S[i]);
			}
		}
		sort(H, H + sz);
		bool flag = 0, flag2 = 0; // 是否已有解,是否已有最大解
		for(int i = N - 1; i >= 0; i--){
			for(int j = i - 1; j >= 0; j--){
				if(update(S[i], S[j]) || (flag && S[i] <= res)){
					flag2 = 1;
					break;
				}
				if(update(S[j], S[i])) flag = 1;
			}
			if(flag2) break;
		}
		if(flag2) printf("%d\n", res);
		else printf("no solution\n");
	}
	return 0;
}
3SUM

在计算复杂度理论中, 3SUM问题是指如下的问题:给定一个包含 n 个实数的集合,判断其中是否包含 3 个和为 0 的元素。3SUM

从大到小枚举 d d ,3SUM 方法求解 a , b , c a,b,c ,复杂度 O ( n 3 ) O(n^3) ,求最大值一般会快很多。3SUM 方法可以在 O ( n 2 ) O(n^2) 内搜索到一组可行解,原理是枚举最左侧的元素,不断收缩 b , c b,c 的搜索范围直到遇到 b , c b,c 。这里要求 a , b , c , d a,b,c,d 不相同,3SUM 方法在 a + b + c = d a+b+c=d 时即停止搜索,这里当元素重复时继续搜索,以保证搜索到全部可行解。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define min(a,b)    (((a) < (b)) ? (a) : (b))
#define max(a,b)    (((a) > (b)) ? (a) : (b))
#define abs(x)    ((x) < 0 ? -(x) : (x))
#define INF 0x3f3f3f3f
#define delta 0.85
#define eps 1e-5
#define PI 3.14159265358979323846
#define MAX_N 1000
using namespace std;
int N;
int S[MAX_N];

int main(){
	while(~scanf("%d", &N) && N){
		for(int i = 0; i < N; i++) scanf("%d", S + i);
		sort(S, S + N);
		bool flag = 0;
		int res;
		for(int i = N - 1; i >= 0; i--){
			int d = S[i];
			for(int j = 0; j <= N - 3; j++){
				if(i == j) continue;
				int a = S[j], s = j + 1, t = N - 1;
				while(s < t){
					int b = S[s], c = S[t];
					if(a + b + c == d && b != d && c != d){
						res = d, flag = 1;
						break;
					}
					else if(a + b + c > d) t--;
					else s++;
				}
				if(flag) break;
			}
			if(flag) break;
		}
		if(flag) printf("%d\n", res);
		else printf("no solution\n");
	}
	return 0;
}
发布了91 篇原创文章 · 获赞 1 · 访问量 1593

猜你喜欢

转载自blog.csdn.net/neweryyy/article/details/105294391