POJ 2549 Sumsets(折半枚举+二分)
| Time Limit: 1000MS | Memory Limit: 65536K | |
| Total Submissions: 11946 | Accepted: 3299 |
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
Output
Sample Input
5
2
3
5
7
12
5
2
16
64
256
1024
0
Sample Output
12
no solution
Source
题意
给你一个公式a+b+c=d,让你在同一个集合(元素不同)内满足该条件时d的最大值,注意a b c d均不同。
思路
网上折半搜索的思路一般是将a+b+c=d拆分成 a+b=d-c
优秀的代码
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int inf = -;
int a[];
int main()
{
int n;
while (cin>>n&&n)
{
for (int i = ; i < n; i++)
cin >> a[i];
sort(a, a + n);//从小到大
n--;
int ans = inf;
for (int i = n; i >= ; i--)
{
for (int j = n; j >= ; j--)
{
if (i == j)
continue;
int sum = a[i] - a[j];
for (int l = , r = j - ; l<r;)//剩下用二分
{
if (a[l] + a[r] == sum)
{
if (l != i && r != i)
{
ans = a[i];
break;
}
}
if (a[l] + a[r]>sum)
r--;
else
l++;
}
if (ans != inf)
break;
}
if (ans != inf)
break;
}
if (ans == inf)
printf("no solution\n");
else
printf("%d\n", ans);
}
return ;
}
将a+b,c-d看成两个序列,然后二分查找。 注意不要忘记去重
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<string>
#include<stack>
#include<queue>
#include<iostream>
#include<cmath>
#include<map>
#include<list>
#include<stack>
typedef long long ll;
using namespace std; int n;
int a[]; struct node{
int i,j;
int val;
}b[*]; bool cmp(node a,node b)
{
return a.val<b.val;
} bool comp1(node a,int b)
{
return a.val<b; // 找到第一个val>=b的结构体元素
} bool comp2(node a,int b)
{
return a.val<=b; // 找到第一个val>b的结构体元素
} int main()
{
while(scanf("%d",&n)==&&n)
{
int i,j,k,m,t;
for(i=;i<n;i++)
scanf("%d",a+i);
sort(a,a+n); int len=;
for(i=;i<n;i++)
{
for(j=i+;j<n;j++)
{
if(a[i]!=a[j]) //这里直接判断一下 不同的话再存 以后就可以减少这部判断啦
{
b[len].i=i;
b[len].j=j;
b[len].val=a[i]+a[j]; //存储题意中的 a+b
len++;
}
}
}
sort(b,b+len,cmp); //根据a+b的值从小到大排序 bool flag=false;
for(i=n-;i>=;i--) //之前已经从小到大对sort了 所以直接从最大的开始
{
int d=a[i]; //我们要找的d
for(j=;j<i;j++)
{
if(d!=a[j]) //d不能等于c
{
int cd=d-a[j]; //cd的值就相当于d-c
node* p1=lower_bound(b,b+len,d-a[j],comp1);
node* p2=lower_bound(b,b+len,d-a[j],comp2);//注意我写的两个函数comp, 而且都是作为lower_bound的参数
if(p2-p1!=) //说明存在 a+b==d-c
{
while(p1!=p2) //还要判断一下a,b,c,d是否都不相同
{
if(a[p1->i]!=a[j]&&a[p1->i]!=a[i]&&a[p1->j]!=a[j]&&a[p1->j]!=a[i])
{
flag=true; //符合题意 直接跳出
break;
}
p1++;
}
}
}
if(flag) //符合题意 直接跳出
break; }
if(flag)break; //符合题意 直接跳出 }
if(flag)printf("%d\n",a[i]); //符合题意 直接输出d 也就是a[i]
else printf("no solution\n"); }
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=+;
ll t[maxn],d[maxn*maxn];
struct node
{
ll sum;
int use1,use2;
} c[maxn*maxn];
bool cmp(const node& a,const node& b)
{
return a.sum<b.sum;
}
int main()
{
int n;
while(~scanf("%d",&n),n)
{
int i,j,s=;
for(i=; i<n; i++)
scanf("%lld",&t[i]);
sort(t,t+n);
for(i=; i<n; i++)
for(j=; j<n; j++)
if(i!=j)
{
c[s].sum=t[i]+t[j];
c[s].use1=i;
c[s++].use2=j;
}
sort(c,c+s,cmp);
for(i=; i<s; i++)
d[i]=c[i].sum;
ll ma=-1e17;
for(i=; i<n; i++)
{
for(j=n-; j>=; j--)
{
if(i!=j&&t[j]>ma)
{
ll u=-(t[i]-t[j]);
int id1=lower_bound(d,d+s,u)-d;
int id2=upper_bound(d,d+s,u)-d-;
for(int k=id1;k<id2;k++)
{
int a=c[k].use1,b=c[k].use2;
if(a!=i&&a!=j&&b!=i&&b!=j)
{
ma=t[j];break;
}
}
}
}
}
if(ma!=-1e17)printf("%lld\n",ma);
else printf("no solution\n");
}
return ;
}
POJ 2549 Sumsets(折半枚举+二分)的更多相关文章
- POJ 3977 Subset(折半枚举+二分)
SubsetTime Limit: 30000MS Memory Limit: 65536KTotal Submissions: 6754 Accepted: 1277 D ...
- CSU OJ PID=1514: Packs 超大背包问题,折半枚举+二分查找。
1514: Packs Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 61 Solved: 4[Submit][Status][Web Board] ...
- POJ 2549 Sumsets
Sumsets Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 10593 Accepted: 2890 Descript ...
- 【折半枚举+二分】POJ 3977 Subset
题目内容 Vjudge链接 给你\(n\)个数,求出这\(n\)个数的一个非空子集,使子集中的数加和的绝对值最小,在此基础上子集中元素的个数应最小. 输入格式 输入含多组数据,每组数据有两行,第一行是 ...
- POJ 3977:Subset(折半枚举+二分)
[题目链接] http://poj.org/problem?id=3977 [题目大意] 在n个数(n<36)中选取一些数,使得其和的绝对值最小. [题解] 因为枚举所有数选或者不选,复杂度太高 ...
- Subset POJ - 3977(折半枚举+二分查找)
题目描述 Given a list of N integers with absolute values no larger than 10 15, find a non empty subset o ...
- POJ 2785 4 Values whose Sum is 0(折半枚举+二分)
4 Values whose Sum is 0 Time Limit: 15000MS Memory Limit: 228000K Total Submissions: 25675 Accep ...
- Subset---poj3977(折半枚举+二分查找)
题目链接:http://poj.org/problem?id=3977 给你n个数,找到一个子集,使得这个子集的和的绝对值是最小的,如果有多种情况,输出子集个数最少的: n<=35,|a[i]| ...
- Codeforces H. Prime Gift(折半枚举二分)
题目描述: Prime Gift time limit per test 3.5 seconds memory limit per test 256 megabytes input standard ...
随机推荐
- zuul 性能分析
引用几篇博客, 后续整理自己心得 Zuul 性能测试 https://blog.csdn.net/u013815546/article/details/69669165 VisualVM 使用 htt ...
- React之状态(state)与生命周期
很多时候,我们的页面数据是动态的.所以,我们需要实时渲染页面: 一.用定时函数setInterval() 组件(输出当前时间): index.js: 这样每隔1秒页面就会重新渲染一次,这样传进去的时间 ...
- Lua基础---迭代器
官方的文档说: 迭代器(iterator)是一种对象,它能够用来遍历标准模板库容器中的部分或全部元素,每个迭代器对象代表容器中的确定的地址 在Lua中迭代器是一种支持指针类型的结构,它可以遍历集合的每 ...
- MySQL笔记之多表
貌似很久不写博客了,趁着项目刚完结,记录一下这段时间了解到的一些认识,或许有些地方理解的还不够到位,看到的希望能不吝赐教. 外键 概念 与索引的关系 写法 查询 一对多多对一查询 多对多查询 插入 多 ...
- 目标检测 - Tensorflow Object Detection API
一. 找到最好的工具 "工欲善其事,必先利其器",如果你想找一个深度学习框架来解决深度学习问题,TensorFlow 就是你的不二之选,究其原因,也不必过多解释,看过其优雅的代码架 ...
- linux c++ 多线程心得
好久没写多线程了,工作好几年也没怎么大规模的写过多线程,都是成形的架构里写业务逻辑.偶尔自己写了下,各种踩坑... 1.string 不是线程安全的 一个特例是std::string.在一些STL的实 ...
- Objective C - 2 - 随机数,可变字符串,字符串,SubString
int main(int argc, const char * argv[]) { @autoreleasepool { NSString *outputString = @"1234567 ...
- 创建第一个python程序:‘Hello World!’
安装好python解释器就可以创建第一个仪式程序Helloworld了 1.Python程序的3种运行方式 1.1.Python解释器直接运行 在Windows或者Linux命令行输入python,进 ...
- EP-N8530S USB WIFI 驱动移植
/*********************************************************************** * EP-N8530S USB WIFI 驱动移植 * ...
- laravel 修改重置密码模板
Laravel里我们可以使用php artisan make:auth来生成一套默认的登陆注册重置邮箱的Authentication System,但是如何修改系统发送给用户的重置密码邮件的样式和内容 ...