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 ...
随机推荐
- C++ 各种继承方式的类内存布局
body, table{font-family: 微软雅黑; font-size: 10pt} table{border-collapse: collapse; border: solid gray; ...
- 12.18 微信扫码获取openid与登陆
官方文档: https://open.weixin.qq.com/ 1.先获取code 1-1 配置项目配置文件 wechat: mpAppId: wxd898fcb01713c658 mpAppSe ...
- Django中通过定时任务触发页面静态化的方式
安装 pip install django-crontab 添加应用 INSTALLED_APPS = [ ... 'django_crontab', # 定时任务 ... ] 设置任务的定时时间 在 ...
- 剑指offer--45.二叉树的深度
时间限制:1秒 空间限制:32768K 热度指数:139716 题目描述 输入一棵二叉树,求该树的深度.从根结点到叶结点依次经过的结点(含根.叶结点)形成树的一条路径,最长路径的长度为树的深度. -- ...
- PostgreSQL数据库资料(转)
PostgreSQL数据库资料 转自:http://blog.csdn.net/postgrechina/article/details/49132791 推荐书籍: 概念书籍: <Postgr ...
- TotoiseSVN的使用方法
详细教程 https://www.jianshu.com/p/6b3b7b915332 SVN提交修改 https://jingyan.baidu.com/article/6c67b1d6f524d5 ...
- Tomcat 环境安装
本文以Tmcat 7版本在Windows Server 2012 64位系统下安装讲解,JAVA环境安装配置参见:http://www.cnblogs.com/fklin/p/6670760.html ...
- java项目添加到Tomcat中运行-(项目转换为Dynamic Web Project)
当在eclipse中建了一个java project项目希望他运行在Tomcat中时: 在项目上右键单击,选择 Properties: 在左侧选择 Project Facets,单击右侧的 ”Conv ...
- [Shell]bash的良好编码实践
最好的bash脚本不仅可以工作,而且以易于理解和修改的方式编写.很多好的编码实践都是来自使用一致的变量名称和一致的编码风格.验证用户提供的参数是否正确,并检查命令是否能成功运行,以及长时间运行是否能保 ...
- ios逆向工程-动态分析
先说说为什么要分析应用吧,如果你想从一个ios应用中获取有用的信息,或者你想修改该应用的一些功能,前提当然是要先知道该app的逻辑和结构了. 动态分享工具比较少,我们先分析个简单的,全民工具Cycri ...