题意
传送门 POJ 2549
折半枚举
枚举 排序之,枚举 二分求满足 且元素不重复的最大 ,复杂度 。
#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
从大到小枚举 ,3SUM 方法求解 ,复杂度 ,求最大值一般会快很多。3SUM 方法可以在 内搜索到一组可行解,原理是枚举最左侧的元素,不断收缩 的搜索范围直到遇到 。这里要求 不相同,3SUM 方法在 时即停止搜索,这里当元素重复时继续搜索,以保证搜索到全部可行解。
#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;
}