qwb和李主席

qwb和李主席

Time Limit: 4 Sec  Memory Limit: 128 MB

Description

qwb和李主席打算平分一堆宝藏,他们想确保分配公平,可惜他们都太懒了,你能帮助他们嘛?

Input

输入包含多组测试数据,处理到文件结束。

每组测试数据的第一行是一个正整数N(0 <= N <=36 )表示物品的总个数.。

接下来输入N个浮点数(最多精确到分),表示每个物品的价值V(0<V<=1e9)。

Output

对于每组测试数据,输出能够使qwb和李主席各自所得到的物品的总价值之差的最小值(精确到分),每组测试数据输出占一行。

Sample Input

3 0.01 0.1 1
2 1 1

Sample Output

0.89
0.00
分析:n很小v很大的情况下不能背包;
   考虑折半搜索,枚举其中一半,然后在另一半中二分即可;
   注意浮点数*200倍变偶数取整的技巧;
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <climits>
#include <cstring>
#include <string>
#include <set>
#include <bitset>
#include <map>
#include <queue>
#include <stack>
#include <vector>
#include <cassert>
#include <ctime>
#include<unordered_map>
#define rep(i,m,n) for(i=m;i<=n;i++)
#define mod 1000000007
#define inf 0x3f3f3f3f
#define vi vector<int>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define ll long long
#define pi acos(-1.0)
#define pii pair<int,int>
#define sys system("pause")
const int maxn=5e4+10;
const int N=5e2+10;
using namespace std;
ll gcd(ll p,ll q){return q==0?p:gcd(q,p%q);}
ll qpow(ll p,ll q){ll f=1;while(q){if(q&1)f=f*p%mod;p=p*p%mod;q>>=1;}return f;}
int n,m,k,t;
ll a[1<<18],b[1<<18],c[18],d[18];
void gao(ll d[],ll a[],int num)
{
    for(int i=0;i<(1<<num);i++)
    {
        d[i]=0;
        for(int j=0;j<num;j++)
        {
            if(i>>j&1)
            {
                d[i]+=a[j];
            }
        }
    }
}
int main()
{
    int i,j;
    while(~scanf("%d",&n))
    {
        int cnta=0,cntb=0;
        ll sum=0;
        rep(i,1,n)
        {
            double x;
            scanf("%lf",&x);
            ll y=round(x*200);  //(ll)(x*200+0.1);
            sum+=y;
            if(i<=n/2)c[cnta++]=y;
            else d[cntb++]=y;
        }
        gao(a,c,cnta);
        gao(b,d,cntb);
        cnta=(1<<cnta);
        cntb=(1<<cntb);
        sort(b,b+cntb);
        ll ret=1e18;
        rep(i,0,cnta-1)
        {
            int pos=lower_bound(b,b+cntb,sum/2-a[i])-b;
            if(pos<cntb)ret=min(ret,abs(sum-2*(a[i]+b[pos])));
            if(pos-1>=0)ret=min(ret,abs(sum-2*(a[i]+b[pos-1])));
        }
        printf("%.2f
",ret/200.0);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/dyzll/p/6935709.html