0%

礼物

在双胞胎兄弟小A与小B的生日会上,他们共收到了N个礼物,生日过后他们决定分配这N个礼物(cntA+cntB=N)(cntA,cntB表示A和B最终得到的礼物数)。对于每个礼物他们俩有着各自心中的价值A_i和B_i,他们要求各自分到的礼物数目|cntA-cntB|<=1,并且各自所衡量的礼物价值的差值|sumA-sumB|尽可能小,现在他们想知道最小的差值是多少。

输入描述:

每组数据第一行为一个整数N,表示礼物数, N<=30
第二行有N个整数,表示小A所衡量的每个礼物的价值A_i。
第三行也有N个整数,表示小B所衡量的每个礼物的价值B_i。

输出描述:

输出最小的差值。

示例1
输入

3
1 2 3
4 2 1

输出

1

liwu.cppview raw
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<vector>
#include<stdlib.h>
#define M 40
using namespace std;
vector<int>R[M];
int A[M],B[M],n,ans;
void check(int &a,int b){
if(a==-1||a>b)a=b;
}
void solve(int sum,int c){//c表示小A在右边需要的礼物数
int id=lower_bound(R[c].begin(),R[c].end(),sum)-R[c].begin();
if(id!=(int)R[c].size())
check(ans,abs(sum-R[c][id]));
if(id>0)
check(ans,abs(sum-R[c][id-1]));
}
int main(){
int i,j;
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%d",&A[i]);
for(i=0;i<n;i++)
scanf("%d",&B[i]);
int m=n/2;
for(i=0;i<=n;i++)R[i].clear();
for(i=0;i<(1<<(n-m));i++){//预处理右半部分
int sum=0,c=0;
for(j=0;j<n-m;j++){
if(i&(1<<j)){
sum-=A[m+j],c++;
}else sum+=B[m+j];
}
R[c].push_back(sum);//sumB-sumA
}
for(i=0;i<=n-m;i++)sort(R[i].begin(),R[i].end());//每个个数对应的vector排序
ans=-1;
for(i=0;i<(1<<m);i++){//枚举左边分配情况
int L=0,c=0;
for(j=0;j<m;j++)
if(i&(1<<j)){//sumA-sumB
L+=A[j],c++;
}else L-=B[j];
if(n&1)solve(L,n/2+1-c);
solve(L,n/2-c);
}
printf("%d\n",ans);
return 0;
}