Poj 3977 Subset 折半枚举 超大背包
来源:互联网 发布:i5处理器编程够用么 编辑:程序博客网 时间:2024/05/16 09:11
第一次wa代码:#include <iostream>
#include<cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <queue>
#include<map>
#include <algorithm>
#include <set>
using namespace std;
#define MM(a) memset(a,0,sizeof(a))
typedef long long ll;
typedef unsigned long long ULL;
const int mod = 1000000007;
const double eps = 1e-10;
const long long inf = 1e17;
struct Node{
ll v, l;
};
Node node1[3000000], node2[3000000],nod[3000000];
ll a[40];
ll absx(ll a)
{
return a > 0 ? a : -a;
}
bool cmp(Node a, Node b)
{
if(a.v!= b.v)
return a.v<b.v;
else return a.l<b.l;
}
ll binary(ll m, ll n)
{
ll l = 0, r = n;
while (r - l>1)
{
ll mid = (l + r) >> 1;
if (nod[mid].v >= m)
r = mid;
else l = mid;
}
return r;
}
int main()
{
ll n;
while (~scanf("%lld", &n)&&n)
{
for (ll i = 1; i <= n; i++)
scanf("%lld", &a[i]);
ll n1 = n / 2,n2=n-n1,minn = inf, mlen = 40;;
ll cnt1 = (1<<n1)-1, cnt2 = (1<<n2)-1;
for (ll i = 1; i <=cnt1; i++)
{
node1[i].v = node1[i].l = 0;
for (ll j = 0; j <=n1-1; j++)
if (i&(1<<j))
{
node1[i].v += a[j+1];
node1[i].l++;
}
ll temp=absx(node1[i].v);
if(minn>temp)
{
minn=temp;
mlen=node1[i].l;
}
else if(minn==temp&&mlen>node1[i].l)
mlen=node1[i].l;
}
for (ll i = 1; i <=cnt2; i++)
{
node2[i].v = node2[i].l = 0;
for (ll j = 0; j <=n2-1; j++)
if (i&(1<<j))
{
node2[i].v += a[n1+j+1];
node2[i].l++;
}
ll temp=absx(node2[i].v);
if(minn>temp)
{
minn=temp;
mlen=node2[i].l;
}
else if(minn==temp&&mlen>node2[i].l)
mlen=node2[i].l;
}
sort(node2 + 1,node2 +cnt2+1, cmp);
nod[1].v=node2[1].v;
nod[1].l=node2[1].l;
ll p=1;
for(ll i=2;i<=cnt2;i++)
if(node2[i].v!=nod[p].v)
{
++p;
nod[p].v=node2[i].v;
nod[p].l=node2[i].l;
}
for (ll i = 1; i <=cnt1; i++)
{
ll m = node1[i].v;
ll j = binary(-m,p);
if (absx(m + nod[j].v)<minn)
{
minn = absx(m + nod[j].v);
mlen = node1[i].l + nod[j].l;
}
else if (minn ==absx(m + nod[j].v))
if (mlen>node1[i].l + nod[j].l)
mlen = node1[i].l + nod[j].l;
j--;
if(j==0) continue;
if (absx(m + nod[j].v)<minn)
{
minn = absx(m + nod[j].v);
mlen = node1[i].l + nod[j].l;
}
else if (minn == absx(m + nod[j].v))
if (mlen>node1[i].l + nod[j].l)
mlen = node1[i].l + nod[j].l;
}
printf("%lld %lld\n", minn, mlen);
}
return 0;
}
#include <iostream>
#include<cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <queue>
#include<map>
#include <algorithm>
#include <set>
using namespace std;
#define MM(a) memset(a,0,sizeof(a))
typedef long long ll;
typedef unsigned long long ULL;
const int mod = 1000000007;
const double eps = 1e-10;
const int inf = 0x3f3f3f3f;
struct Node{
ll v, l;
};
Node node1[3000000], node2[3000000];
int a[40];
ll absx(ll a)
{
return a > 0 ? a : -a;
}
bool cmp(Node a, Node b)
{
return a.v < b.v;
}
ll binary(int m, int n)
{
ll l = 0, r = n;
while (r - l>1)
{
ll mid = (l + r) >> 1;
if (node2[mid].v >= m)
r = mid;
else l = mid;
}
return r;
}
int main()
{
ll n;
while (~scanf("%lld", &n)&&n)
{
for (ll i = 1; i <= n; i++)
scanf("%lld", &a[i]);
ll n1 = n / 2,n2=n-n1;
ll cnt1 = (1<<n1), cnt2 = (1<<n2);
for (ll i = 0; i <cnt1; i++)
{
node1[i].v = node1[i].l = 0;
for (ll j = 1; j < (1<<n1); j <<= 1)
if (i&j)
{
node1[i].v += a[j];
node1[i].l++;
}
}
for (ll i = 0; i < cnt2; i++)
{
node2[i].v = node2[i].l = 0;
for (ll j = 1; j <(1<<n2); j <<= 1)
if (i&j)
{
node2[i].v += a[n1+j];
node2[i].l++;
}
}
sort(node2 + 1,node2 +cnt2, cmp);
node2[0].l = node2[0].v = 0;
ll minn = inf, mlen = 40;
for (ll i = 0; i < cnt1; i++)
{
ll m = node1[i].v;
ll j = binary(-m,n2);
if (absx(m + node2[j].v)<minn)
{
minn = absx(m + node2[j].v);
mlen = node1[i].l + node2[j].l;
}
else if (minn = absx(m + node2[j].v))
if (mlen>node1[i].l + node2[j].l)
mlen = node2[i].l + node2[j].l;
j--;
if (absx(m + node2[j].v)<minn)
{
minn = absx(m + node2[j].v);
mlen = node1[i].l + node2[j].l;
}
else if (minn == absx(m + node2[j].v))
if (mlen>node1[i].l + node2[j].l)
mlen = node2[i].l + node2[j].l;
}
printf("%lld %lld\n", minn, mlen);
}
return 0;
}
- Poj 3977 Subset 折半枚举 超大背包
- poj 3977 Subset 折半枚举
- POJ - 3977 Subset(折半枚举)
- POJ 3977 Subset (折半枚举)
- POJ 3977 Subset (折半枚举+二分)
- POJ 3977 Subset (简单折半枚举)
- 超大背包问题 折半枚举
- 超大背包问题 (折半枚举)
- 超大背包问题(折半枚举)
- 超大背包问题 (折半枚举)
- 超大背包问题 折半枚举法
- poj 3977 Subset(折半枚举+状压dp)
- POJ 3977 Subset(折半枚举 + 二分查找)
- 超大的变体背包问题(折半枚举/双向搜索)
- POJ3977 Subset 折半枚举
- poj3977 Subset 折半枚举
- POJ3977-Subset 折半枚举
- poj 3977 Subset 枚举+二分
- POj 3258 River Hopscotch 二分搜索 最大化最小值
- poj 2674 Linear world 弹性碰撞 升级的蚂蚁
- poj 2785 4 Values whose Sum is 0
- Codeforces Round #324 (Div. 2) A. Olesya and Rodion 构造数字 思维题
- Codeforces Round #324 (Div. 2) B. Kolya and Tanya 思维题 数论
- Poj 3977 Subset 折半枚举 超大背包
- poj 2549 Sumsets 折半枚举
- poj 3276 Face The Right Way 挑战150 反转
- poj 3279 Fliptile 反转
- poj 3185 The Water Bowls 反转(开关)
- poj 1930 Dead Fraction 循环小数的处理
- poj 3421 X-factor Chains 素数筛选 因子分解
- poj 3292 Semi-prime H-numbers 素数变形+打表+筛选法
- poj 3468 A Simple Problem with Integers 模板题 线段树 懒惰标记