Problem Description

在双胞胎兄弟Eric与R.W的生日会上,他们共收到了N个礼物,生日过后他们决定分配这N个礼物(numv+numw=N)。对于每个礼物他们俩有着各自心中的价值vi和wi,他们要求各自分到的礼物数目|numv-numw|<=1,并且各自所衡量的礼物价值的差值|sumv-sumw|尽可能小,现在他们想知道最小的差值是多少。

 Input

第一行为一个整数表示数据组数T。 接下来T组数组,每组数据第一行为一个整数N。(N<=30) 第二行有N个整数,表示Eric所衡量的每个礼物的价值vi。(1<=vi<=10000000) 第三行也有N个整数,表示R.W所衡量的每个礼物的价值wi。(1<=wi<=10000000)

 Output

对于每组数据,输出最小的差值。

 Sample Input

131  2  34  2  1

 Sample Output

1

思路:这题一开始比较容易想到的是把所有状态都枚举一遍,但是这样的复杂度为2^30次,稳稳的超时了。所以我们可以把n件物品拆成两半,前一半的个数为n/2,后一半的个数为n-n/2。然后我们先预处理出前一半的状态,用c[i][j]表示前一半有i件物品给eric的第j种情况sumv-sumw的值。然后对于每一个i,0<=i<=n/2,我们进行从小到大排序,这里的排序是为了之后的二分。接着,我们就可以处理后一半了,枚举后一半的所有状态(0~(1<<m2)-1),算出sumw-sumv的值,记录次状态下eric取的个数num,然后在c[n/2-num]中找到最接近sumw-sumv的值就行了。 

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <stack>
using namespace std;
#define maxn 100050
#define inf 999999999
int v[40],w[40];
int c[17][1<<16],d[17]; int chazhao(int num,int sum)
{
int i,j,t,p1,p2,minx=inf;
t=lower_bound(c[num]+1,c[num]+1+d[num],sum )-c[num];
if(t==d[num]+1){
t--;
minx=min(minx,abs(c[num][t]-sum) ); }
else{
p1=t;p2=t;
if(p1!=1){
p1--;
minx=min(minx,abs(c[num][p1]-sum) );
}
minx=min(minx,abs(c[num][t]-sum));
if(p2!=d[num]){
p2++;
minx=min(minx,abs(c[num][p2]-sum) );
}
}
return minx;
} int main()
{
int n,m,i,j,T,m1,m2,state,tot,num,sum,t,p1,p2;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(i=1;i<=n;i++){
scanf("%d",&v[i]);
}
for(i=1;i<=n;i++){
scanf("%d",&w[i]);
}
m1=n/2;
m2=n-m1;
memset(d,0,sizeof(d));
for(state=0;state<(1<<m1);state++){
tot=0;sum=0;
for(i=1;i<=m1;i++){
if(state&(1<<(i-1) )){
tot++;
sum+=v[i];
}
else sum-=w[i];
}
d[tot]++;
c[tot][d[tot] ]=sum;
}
for(i=0;i<=m1;i++){
sort(c[i]+1,c[i]+1+d[i]);
} int minx=inf;
for(state=0;state<(1<<m2);state++){
tot=0;sum=0;
for(i=1;i<=m2;i++){
if(state&(1<<(i-1))){
tot++;
sum-=v[m1+i];
}
else sum+=w[m1+i];
}
if((n%2==1) && (tot!=0) ){
num=n/2+1-tot;
minx=min(minx,chazhao(num,sum));
}
num=n/2-tot;
minx=min(minx,chazhao(num,sum));
}
printf("%d\n",minx);
}
return 0;
}

fzu2178礼物分配 (状压+二分)的更多相关文章

  1. Luogu P3092 [USACO13NOV]没有找零No Change【状压/二分】By cellur925

    题目传送门 可能是我退役/NOIP前做的最后一道状压... 题目大意:给你\(k\)个硬币,FJ想按顺序买\(n\)个物品,但是不能找零,问你最后最多剩下多少钱. 注意到\(k<=16\),提示 ...

  2. NOIP2016提高A组 A题 礼物—概率状压dp

    题目描述 夏川的生日就要到了.作为夏川形式上的男朋友,季堂打算给夏川买一些生 日礼物. 商店里一共有n种礼物.夏川每得到一种礼物,就会获得相应喜悦值Wi(每种礼物的喜悦值不能重复获得). 每次,店员会 ...

  3. 2018.08.19 NOIP模拟 dp(二分+状压dp)

    Dp 题目背景 SOURCE:NOIP2015-SHY-10 题目描述 一块土地有 n 个连续的部分,用 H[1],H[2],-,H[n] 表示每个部分的最初高度.有 n 种泥土可用,他们都能覆盖连续 ...

  4. 【BZOJ3312】[Usaco2013 Nov]No Change 状压DP+二分

    [BZOJ3312][Usaco2013 Nov]No Change Description Farmer John is at the market to purchase supplies for ...

  5. 【9.7校内测试】【二分+spfa】【最长上升子序列】【状压DP+贪心(?)】

    刘汝佳蓝书上的题,标程做法是从终点倒着$spfa$,我是二分答案正着$spfa$判断可不可行.效果是一样的. [注意]多组数据建边一定要清零啊QAQ!!! #include<iostream&g ...

  6. hdu 3681(bfs+二分+状压dp判断)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3681 思路:机器人从出发点出发要求走过所有的Y,因为点很少,所以就能想到经典的TSP问题.首先bfs预 ...

  7. HDU-3681-Prison Break(BFS+状压DP+二分)

    Problem Description Rompire is a robot kingdom and a lot of robots live there peacefully. But one da ...

  8. [luoguP3092] [USACO13NOV]没有找零No Change(状压DP + 二分)

    传送门 先通过二分预处理出来,每个硬币在每个商品处最多能往后买多少个商品 直接状压DP即可 f[i]就为,所有比状态i少一个硬币j的状态所能达到的最远距离,在加上硬币j在当前位置所能达到的距离,所有的 ...

  9. 20190716NOIP模拟赛T1 礼物(概率dp+状压)

    题目描述 夏川的生日就要到了.作为夏川形式上的男朋友,季堂打算给夏川买一些生 日礼物. 商店里一共有种礼物.夏川每得到一种礼物,就会获得相应喜悦值Wi(每种 礼物的喜悦值不能重复获得). 每次,店员会 ...

随机推荐

  1. docker基础总结

    搜索镜像docker search ubuntu 搜索ubuntu的Docker镜像 搜索结果单个单词ubuntu这样的镜像,被称为基础镜像或根镜像,这些基础镜像由 Docker 公司创建搜索结果ti ...

  2. MySQL常用的数据类型和字段属性

    数据类型 数值 tinyint 十分小的数据 1个字节 smallint 较小的数据 2个字节 mediumint 中等大小的数据 3个字节 int 标准的整数 4个字节 常用 bigint 较大的数 ...

  3. 基于Dockfile构建JAVA环境网站镜像

    查看本地目录 [root@docker tomcat]# ls apache-tomcat-8.5.16.tar.gz  Dockerfile  jdk-8u91-linux-x64.tar.gz   ...

  4. vagrant up报错【io.rb:32:in `encode': "\x95" followed by "\"" on GBK (Encoding::InvalidByteSequenceError)】

    vagrant up报错[io.rb:32:in `encode': "\x95" followed by """ on GBK (Encoding: ...

  5. 解决ubuntu获取root账号并开通ssh

    1.设置root密码 sudo passwd root 2.修改etc/ssh/sshd_config文件 su - root vi /etc/ssh/sshd_config LoginGraceTi ...

  6. .NET Core 问题记录

    前言: 最近在项目中遇到了遇到了写部署步骤过多的问题,为了减少.net core项目部署步骤:需要对一些基础问题进行验证: 如端口设置.单页应用程序(angluar)合并部署方式等相关问题,特将解决过 ...

  7. 前端知识(一)06 element-ui-谷粒学院

    目录 一.element-ui 二.element-ui实例 1.引入脚本库 2.引入css 3.引入js 4.渲染讲师列表 5.浏览器中运行 一.element-ui element-ui 是饿了么 ...

  8. 不用git 手动对比文件差异

    使用python脚本比较两个文件的差异内容并输出到html文档中,可以通过浏览器打开查看. 一.脚本使用 对比文件的差异 python python_diff_file.py -f1 web26.co ...

  9. winform 扫码识别二维码

    因为公司业务需求,需要在Windows系统下调用摄像头识别二维码需求,就有了这个功能. 我根据网上网友提供的一些资料,自己整合应用到项目中,效果还不错(就是感觉像素不是太好) 现在将调用摄像头+识别二 ...

  10. 使用remix实现给合约账户转账

    实现内容:从remix上的虚拟账户上转账给自己编写的智能合约账户 前提基础:对solidity有一些基础了解,对以太坊的账户机制有一定了解. 账户 在以太坊中账户的唯一标识是地址(address). ...