uva 10125和集 sumset(set)

给定数字集合,找出最大的d,使得a+b+c=d且abc均在数字集合中,集合元素数量不超过1000

思路是把等式变换为d-c=a+b,这样只要枚举d,c,验证d-c是否在任意两元素之和所在的集合中,注意abcd不能重复,所以需要一些额外的判重条件

#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<vector>
#include<map>
#include<queue>
#include<stack>
#include<string>
#include<map>
#include<set>
#define eps 1e-6
#define LL long long
using namespace std;  

const int maxn = 1000 + 5;
const int INF = 0x3f3f3f3f;
//freopen("input.txt", "r", stdin);
multiset<int> su;
set<int> sumset;
int S[maxn];
int n;

void init() {
	su.clear();
	for(int i = 0; i < n; i++) { scanf("%d", &S[i]); sumset.insert(S[i]); }
	for(int i = 0; i < n-1; i++)
		for(int j = i + 1; j < n; j++) { su.insert(S[i]+S[j]); }
}

void solve() {
	int ans = -INF;
	for(int i = 0; i < n-1; i++)
		for(int j = i + 1; j < n; j++) {
			int cnt = 0;
			if(sumset.count(-S[j])) cnt++; if(sumset.count(S[i]-2*S[j])) cnt++;
			if(!S[j]) cnt--;
			if(su.count(S[i]-S[j])>cnt) ans = max(ans, S[i]);
			cnt = 0;
			if(sumset.count(-S[i])) cnt++; if(sumset.count(S[j]-2*S[i])) cnt++;
			if(!S[i]) cnt--;
			if(su.count(S[j]-S[i])>cnt) ans = max(ans, S[j]);
		}
	if(ans != -INF) printf("%d\n", ans);
	else puts("no solution");
}

int main() {
	//freopen("input.txt", "r", stdin);
	while(scanf("%d", &n) == 1 && n) {
		init();
		solve();
	}
	return 0;
}
时间: 2024-08-26 13:57:27

uva 10125和集 sumset(set)的相关文章

UVa 10125 - Sumsets

题目:给你n个数让你在里面找到会不相同的4个数a,b,c,d,使得 d = a + b + c. 分析:数学题,散列表.这是一个优化问题. 方法1:暴力法: 先排序,然后直接利用四层循环求解,找到解后直接跳出,也可以以利用二分代替最后一层循环: 这种方法,如果遇到特殊的数据就会TLE: 方法2:分步计算: 将等式转化为 d - a = b + c:我们分别求解两边的结果,然后找到结果相同的值即可: 查找方法,可以使用散列表储存b + c 或 a + b 的值,供另一边查找:也可存进数组,二分查找

【HASH】【UVA 10125】 Sumset

传送门 Description 给定一个整数集合S,求一个最大的d,满足a+b+c=d,其中a,b,c,d∈S Input 多组数据,每组数据包括: 第一行一个整数n,代表元素个数 下面n行每行一个整数,代表集合元素 输入结束的标志为n=0. Output 对于每组数据,输出: 一行,如果有解,输出一个整数,代表最大的d:否则输出no solution Sample Input 5 2 3 5 7 12 5 2 16 64 256 1024 0 Sample Output 12 no solut

uva 10125 - Sumsets(a+b+c=d)

希望下次能马上想到 a+b .d-c 分开来算.然后保存其中一项的值,算出另一项来就查找该值是否存在. 这种方法明显比三重循环省时. 还有下面的方法: 三重循环穷举a,b,d;然后二分穷举c: #include<stdio.h> #include<algorithm> #include<string.h> using namespace std; int a[1010],i,j,k,ans,f,n; int comp(int x,int y) { return x>

UVA 572 油田连通块-并查集解决

题意:8个方向如果能够连成一块就算是一个连通块,求一共有几个连通块. 分析:网上的题解一般都是dfs,但是今天发现并查集也可以解决,为了方便我自己理解大神的模板,便尝试解这道题目,没想到过了... 1 #include <cstdio> 2 #include <iostream> 3 #include <sstream> 4 #include <cmath> 5 #include <cstring> 6 #include <cstdlib&

UVA - 11987 - Almost Union-Find (又是并查集~)

UVA - 11987 Almost Union-Find Time Limit: 1000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu Submit Status Description Problem A Almost Union-Find I hope you know the beautiful Union-Find structure. In this problem, you're to implement som

UVA - 10596 - Morning Walk (欧拉回路!并查集判断回路)

UVA - 10596 Morning Walk Time Limit: 3000MS Memory Limit: Unknown 64bit IO Format: %lld & %llu Submit Status Description Problem H Morning Walk Time Limit 3 Seconds Kamal is a Motashota guy. He has got a new job in Chittagong . So, he has moved to Ch

uva 10608 Friends(并查集)

uva 10608 Friends 题目大意:给出两两之间的关系,求出最大的关系网. 解题思路:并查集裸体. #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <cstdlib> using namespace std; const int N = 30005; typedef long long ll; int n, m; in

并查集间单个节点的转移(UVa 11987 Almost Union-Find)

从来没有这么艰难地完成一道算法题过!经过8次失败之后总算提交成功了!所以决定写一篇博文,对并查集的相关内容做一些总结. 普通并查集的操作无非是两种,find_set(x)即找到节点x所在的集合的代表节点,或者是union_set(x,y),即将x和y所在的两个集合合并起来.如下图所示,有左右两个并集 通常,我们会选用并查集中父节点为自己的元素作为这个并查集的代表,例如图中的节点a和节点e.那么,我们如何通过集合中的一个节点找到该节点所在集合的代表节点呢?其实很简单,例如上图中的d节点,它首先通过

uva 1455 - Kingdom(并查集+线段树)

题目链接:uva 1455 - Kingdom 题目大意:平面上又n个城市,初始时城市之间没有任何双向道路相连,要求一次执行指令. road A B :在城市A和城市B之间连接一条双向道路 line C:询问一条y=C的水平线上穿过多少州和这些州总共有多少城市. 一个联通分量算一个州,C保证为小数部分为0.5的实数. 解题思路:线段树维护每个位置上州和城市的个数,并查集维护哪些城市属于同一个州,并且要记录这些州上下范围.每次新建一条道路,要相应根据两个州的y坐标范围对线段树进行维护. #incl