原题

给定N个整数组成的数列(N<=35),从中选出一个子集,使得这个子集的所有元素的值的和的绝对值最小,如果有多组数据满足的话,选择子集元素最少的那个。


n<=35,所以双向dfs的O(2^(n/2))可以直接解决问题。因为会爆空间,所以枚举前一半的二进制状态来完成dfs,并用map记录每个状态所用的个数,然后枚举后一半的状态在map中找第一个大于等于他的和第一个小于他的,比较这两个答案。

注:long long 没有自带的abs,并且在define里要多打括号,因为优先度……

#include<cstdio>
#include<map>
#define abs(x) ((x)>0?(x):-(x))
typedef long long ll;
using namespace std;
ll n,a[40],ans,sum;
int cnt;
map <ll,int> mp;
map <ll,int> :: iterator qwq; ll read()
{
ll ans=0,fu=1;
char j=getchar();
for (;(j<'0' || j>'9') && j!='-';j=getchar()) ;
if (j=='-') j=getchar(),fu=-1;
for (;j>='0' && j<='9';j=getchar()) ans*=10,ans+=j-'0';
return ans*fu;
} int main()
{
while (~scanf("%lld",&n) && n)
{
mp.clear();
ans=0;
cnt=0;
for (int i=1;i<=n;i++)
a[i]=read();
ans=abs(a[1]);
cnt=1;
for (int i=1,j,now,count;i<(1<<(n/2));i++)
{
sum=0;
j=i;
now=0;
count=0;
while (j)
{
if (j&1)
sum+=a[now+1],count++;
j>>=1;
now++;
}
if (abs(sum)<ans)
{
ans=abs(sum);
cnt=count;
}
else if (abs(sum)==ans) cnt=min(cnt,count);
if (mp[sum])
mp[sum]=min(mp[sum],count);
else
mp[sum]=count;
}
for (int i=1,j,now,count;i<(1<<(n-n/2));i++)
{
j=i;
sum=0;
count=0;
now=0;
while (j)
{
if (j&1)
sum+=a[now+n/2+1],count++;
j>>=1;
now++;
}
if (abs(sum)<ans)
{
ans=abs(sum);
cnt=count;
}
else if (abs(sum)==ans) cnt=min(cnt,count);
qwq=mp.lower_bound(-sum);
ll nw;
if (qwq!=mp.end())
{
nw=sum+qwq->first;
nw=abs(nw);
if (nw<ans)
{
ans=nw;
cnt=qwq->second+count;
}
else if (nw==ans) cnt=min(cnt,qwq->second+count);
}
if (qwq!=mp.begin())
{
qwq--;
nw=sum+qwq->first;
nw=abs(nw);
if (nw<ans)
{
ans=nw;
cnt=qwq->second+count;
}
else if (nw==ans) cnt=min(cnt,qwq->second+count);
}
}
printf("%lld %d\n",ans,cnt);
}
return 0;
}

[poj] 3977 Subset || 折半搜索MITM的更多相关文章

  1. POJ 3977 Subset | 折半搜索

    题目: 给出一个整数集合,求出非空子集中元素和绝对值最小是多少(元素个数尽量少) 题解: 分成两半 爆搜每一半,用map维护前一半的值 每搜出后一半的一个值就去map里找和他和绝对值最小的更新答案 # ...

  2. POJ 3977 - subset - 折半枚举

    2017-08-01 21:45:19 writer:pprp 题目: • POJ 3977• 给定n个数,求一个子集(非空)• 使得子集内元素和的绝对值最小• n ≤ 35 AC代码如下:(难点:枚 ...

  3. POJ 3977 Subset(折半枚举+二分)

    SubsetTime Limit: 30000MS        Memory Limit: 65536KTotal Submissions: 6754        Accepted: 1277 D ...

  4. poj 3977 Subset(折半枚举+二进制枚举+二分)

    Subset Time Limit: 30000MS   Memory Limit: 65536K Total Submissions: 5721   Accepted: 1083 Descripti ...

  5. 【折半枚举+二分】POJ 3977 Subset

    题目内容 Vjudge链接 给你\(n\)个数,求出这\(n\)个数的一个非空子集,使子集中的数加和的绝对值最小,在此基础上子集中元素的个数应最小. 输入格式 输入含多组数据,每组数据有两行,第一行是 ...

  6. POJ - 3977 Subset(二分+折半枚举)

    题意:有一个N(N <= 35)个数的集合,每个数的绝对值小于等于1015,找一个非空子集,使该子集中所有元素的和的绝对值最小,若有多个,则输出个数最小的那个. 分析: 1.将集合中的元素分成两 ...

  7. POJ 3977 Subset

    Subset Time Limit: 30000MS   Memory Limit: 65536K Total Submissions: 3161   Accepted: 564 Descriptio ...

  8. POJ3977:Subset——题解(三分+折半搜索)

    http://poj.org/problem?id=3977 题目大意:有一堆数,取出一些数,记他们和的绝对值为w,取的个数为n,求在w最小的情况下,n最小,并输出w,n. ————————————— ...

  9. bzoj2679: [Usaco2012 Open]Balanced Cow Subsets(折半搜索)

    2679: [Usaco2012 Open]Balanced Cow Subsets Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 462  Solv ...

随机推荐

  1. 线段树的应用xx中学模拟lites

    跟昨天那个自己写的,没有按照模板来的一看风格就不相类似,今天模拟赛的时候就是用的我的那个自己YY的代码,才拿了10分.个人认为关键的问题应该在于对于数据的处理太过繁琐了,所以回来之后,就拿了大佬的程序 ...

  2. 【例题收藏】◇例题·I◇ Snuke's Subway Trip

    ◇例题·I◇ Snuke's Subway Trip 题目来源:Atcoder Regular 061 E题(beta版) +传送门+ 一.解析 (1)最短路实现 由于在同一家公司的铁路上移动是不花费 ...

  3. tcp文件下载客户端+服务端

    客户端: import socket if __name__ == '__main__': # 创建tcp客户端socket tcp_client_socket = socket.socket(soc ...

  4. pycharm界面美化,个人喜欢

    进入file-setting选项 界面设置主要是在appearance和editor里面.appearance主要是整个pycharm的主题设置,比如文件管理窗口的颜色,其实就是软件本身的主题设置.我 ...

  5. keepalived实现nginx的高可用

    1.使用yum安装keepalived yum install keepalived -y 2.修改配置文件keepalived.conf 主服务器配置文件 global_defs { router_ ...

  6. bootloader 关闭看门狗

    #define pWTCON 0x53000000disable_watchdog: ldr r0, =pWTCON mov r1, #0x0 str r1, [r0]

  7. Python9-数据类型-day3

    数据类型转换 #int----->str s = 1 i = str(s) print(i) #str----->int s = ' i = int(s) print(i) #int--- ...

  8. 013---Django的分页器

    知识预览 分页 Django的分页器(paginator) view from django.shortcuts import render, HttpResponsefrom app01.model ...

  9. [Codeforces86D]Powerful array(莫队算法)

    题意:定义K[x]为元素x在区间[l,r]内出现的次数,那么它的贡献为K[x]*K[x]*x 给定一个序列,以及一些区间询问,求每个区间的贡献 算是莫队算法膜版题,不带修改的 Code #includ ...

  10. impala presto SparkSql性能测试对比

      目标是为测试impala presto SparkSql谁的性能更佳,以下结果底层查询的都是普通textfile snappy压缩后数据,规模为15台机器,若以orcfile.parquet速度能 ...