原题:qwb和李主席
原题大意
qwb和李主席打算平分一堆宝藏,他们想确保分配公平,可惜他们都太懒了,你能帮助他们嘛?
输入包含多组测试数据,处理到文件结束。
每组测试数据的第一行是一个正整数N(0 <= N <=36 )表示物品的总个数。
接下来输入N个浮点数(最多精确到分),表示每个物品的价值V(0<V<=1e9)。
对于每组测试数据,输出能够使qwb和李主席各自所得到的物品的总价值之差的最小值(精确到分),每组测试数据输出占一行。
算法分析
折半搜索+二分查找,注意可能会因为浮点数误差导致WA,解决方法是一开始*200化成LL,
程序代码
#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
const int maxn = 40;
ll N[maxn], a[maxn], b[maxn], sum1[1<<20], all_cost;
int n, na, nb;
int main() {
while(~scanf("%d", &n)){
na = nb = 0;
all_cost = 0LL;
for(int i = 1; i <= n; i++){
double t;
scanf("%lf", &t);
N[i] = round(t*200);
if(i < n/2){
a[na++] = N[i];
}
else{
b[nb++] = N[i];
}
all_cost+=N[i];
}
memset(sum1,0,sizeof(sum1));
for(int i = 0; i <(1<<na); i++){
ll sum = 0LL;
for(int j = 0; j < na; j++){
if(i & (1<<j)) sum += a[j];
}
sum1[i] = sum;
}
sort(sum1,sum1+(1<<na));
ll ans = 1e18;
for(int i = 0; i <= (1<<nb); i++){
ll temp = 0LL;
for(int j = 0; j < nb; j++){
if(i & (1 << j)) temp+=b[j];
}
int pos = lower_bound(sum1,sum1+(1<<na),all_cost/2-temp)-sum1;
ans = min(ans, abs((sum1[pos] + temp) - (all_cost-sum1[pos] - temp)));
}
printf("%.2lf\n", ans/200.0);
}
return 0;
}