POJ3977 Subset 折半枚举
题目大意是给定N个数的集合,从这个集合中找到一个非空子集,使得该子集元素和的绝对值最小。假设有多个答案,输出元素个数最少的那个。
N最多为35,假设直接枚举显然是不行的。
可是假设我们将这些数分成两半后再枚举的话,最多有2^18(262144),此时我们两半枚举后的结果进行排序后再二分搜索一下就能够了。复杂度为O(nlogn)
n最多2^18。
#include <stdio.h>
#include <vector>
#include <math.h>
#include <string.h>
#include <string>
#include <iostream>
#include <queue>
#include <list>
#include <algorithm>
#include <stack>
#include <map> using namespace std; struct MyStruct
{
long long res;
int i;
}; int compp(const void* a1, const void* a2)
{
long long dif = ((MyStruct*)a1)->res - ((MyStruct*)a2)->res;
if (dif > 0)
{
return 1;
}
else if (dif == 0)
{
return 0;
}
else
return -1;
} MyStruct res[2][300000]; inline long long absll(long long X)
{
if (X < 0)
{
return X * (-1);
}
else
return X;
} int main()
{
int n;
#ifdef _DEBUG
freopen("d:\\in.txt", "r", stdin);
#endif
long long values[36];
while (scanf("%d", &n) != EOF)
{
if (n == 0)
{
break;
}
for (int i = 0; i < n; i++)
{
scanf("%I64d", &values[i]);
}
int maxn = n - n / 2;
int maxm = n - maxn;
memset(res, 0, sizeof(res));
for (int i = 0; i < 1 << maxn; i++)
{
res[0][i].i = i;
for (int k = 0; k < 19; k++)
{
if ((i >> k) & 1)
{
res[0][i].res += values[k];
}
}
}
qsort(res[0], 1 << maxn, sizeof(MyStruct), compp);
for (int i = 0; i < 1 << maxm; i++)
{
res[1][i].i = i;
for (int k = 0; k < 19; k++)
{
if ((i >> k) & 1)
{
res[1][i].res += values[k + maxn];
}
}
}
qsort(res[1], 1 << maxm, sizeof(MyStruct), compp);
long long minvalue = 1000000000000000LL;
int mink = 32;
int l = 0;
int r = (1 << maxm);
for (int i = 0; i < 1 << maxn; i++)
{
l = 0;
int curk = 0;
for (int k = 0; k < maxn; k++)
{
if ((res[0][i].i >> k) & 1)
{
curk++;
}
}
while (r - l > 1)
{
int mid = (l + r) / 2;
long long sum = res[1][mid].res + res[0][i].res;
if (sum > 0)
{
r = mid;
}
else
l = mid;
} l = l >= 1 ? l - 1 : l;
for (int k = l; k < (1 << maxm);k++)
{
int curm = 0;
for (int m = 0; m < maxm; m++)
{
if ((res[1][k].i >> m) & 1)
{
curm++;
}
}
if (curm == 0 && curk == 0)
{
continue;
}
long long sum = res[1][k].res + res[0][i].res;
if (absll(sum) < minvalue)
{
mink = curm + curk;
minvalue = absll(sum);
}
else if (absll(sum) == minvalue)
{
mink = min(mink, curk + curm);
}
else if (sum > 0)
{
break;
}
}
}
printf("%I64d %d\n", minvalue, mink);
}
return 0;
}
POJ3977 Subset 折半枚举的更多相关文章
- POJ 3977 Subset(折半枚举+二分)
SubsetTime Limit: 30000MS Memory Limit: 65536KTotal Submissions: 6754 Accepted: 1277 D ...
- poj3977(折半枚举+二分查找)
题目链接:https://vjudge.net/problem/POJ-3977 题意:给一个大小<=35的集合,找一个非空子集合,使得子集合元素和的绝对值最小,如果有多个这样的集合,找元素个数 ...
- POJ 3977 - subset - 折半枚举
2017-08-01 21:45:19 writer:pprp 题目: • POJ 3977• 给定n个数,求一个子集(非空)• 使得子集内元素和的绝对值最小• n ≤ 35 AC代码如下:(难点:枚 ...
- poj 3977 Subset(折半枚举+二进制枚举+二分)
Subset Time Limit: 30000MS Memory Limit: 65536K Total Submissions: 5721 Accepted: 1083 Descripti ...
- 折半枚举——poj3977
暴力搜索超时,但是折半后两部分状态支持合并的情况,可用折半枚举算法 poj3977 给一个序列a[],从里面找到k个数,使其和的绝对值最小 经典折半枚举法+二分解决,对于前一半数开一个map,map[ ...
- Load Balancing 折半枚举大法好啊
Load Balancing 给出每个学生的学分. 将学生按学分分成四组,使得sigma (sumi-n/4)最小. 算法: 折半枚举 #include <iostrea ...
- CSU OJ PID=1514: Packs 超大背包问题,折半枚举+二分查找。
1514: Packs Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 61 Solved: 4[Submit][Status][Web Board] ...
- NYOJ 1091 超大01背包(折半枚举)
这道题乍一看是普通的01背包,最最基础的,但是仔细一看数据,发现普通的根本没法做,仔细观察数组发现n比较小,利用这个特点将它划分为前半部分和后半部分这样就好了,当时在网上找题解,找不到,后来在挑战程序 ...
- Codeforces 888E - Maximum Subsequence(折半枚举(meet-in-the-middle))
888E - Maximum Subsequence 思路:折半枚举. 代码: #include<bits/stdc++.h> using namespace std; #define l ...
随机推荐
- createlang - 定义一种新的 PostgreSQL 过程语言
SYNOPSIS createlang [ connection-option...] langname [ dbname] createlang [ connection-option...] -- ...
- 第一天 初识Python
Python基础 一 编程语言 什么是编程语言? 上面提及的能够被计算机所识别的表达方式即编程语言,语言是沟通的介质,而编程语言是程序员与计算机沟通的介质.在编程的世界里,计算机更像是人 ...
- 扩展IHttpHandler
前面提到当请求进入到IIS,IIS转发给ISAPI后会根据文件的后缀名来决定将请求转发给对应的处理程序进行处理,当然一大部分的处理都是交给了AspNet_ISAPI 了.但是,AspNet_ISAPI ...
- jdk5.0新增两个线程创建方法
1.实现callable接口 import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; ...
- 【东软实训】SQL函数
SQL函数 SQL是用于访问和处理数据库的标准的计算机语言,我们所使用的的是Oracle SQL 一个数据库通常包含一个或多个表,每个表有一个名字表示,下图即为一个名为“emp”的表,接下来的操作都将 ...
- 对散列进行sort排序,只是会产生一个顺序,但这顺序和初始化时的顺序不一致
109 my $slice_layouts; 110 my $vertical_assignment; 111 my %map_function_indices = ( 112 ...
- wampsever修改数据库密码
①进入localhost中的mysql数据库 ②再进入mysql数据库中的user表 ③将user表中的三个root账号的密码全部改为你想要的密码(不需要经过MD5加密) ④保存后重新启动服务 如果在 ...
- MySQL与MyBatis中的查询记录
1.时间段查询 MySQL:select * from table where ctime >= CURDATE() and ctime <DATE_SUB(CURDATE(),INTER ...
- 第二次:Ubuntu16.04 系统怎么截图
一开始想着写文章不用图,全靠文字描述,可是我错了,技术类文字没有图怎么能说的清楚,于是乎开始找在Ubuntu系统下的截图工具,网络神奇,发现了这个,以下命令可以反复试试: ubuntu 会自带一款截图 ...
- Python 字典(2)
一.遍历字典 一个字典可能会包含多个键-值对,字典可以以多种方式存储信息,因此有多种遍历字典的方式,比如键-值对.键.值. 1.遍历所有的键-值对 user_01 = {'username':'tiz ...