Problem E: qwb和李主席
Time Limit: 4 Sec Memory Limit: 128 MBSubmit: 422 Solved: 49
[ Submit][ Status][ Web Board]
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
思路:一眼就能看出来是折半枚举。。而傻逼的我还想了好长时间怎么去求最小值。。其实二分不就好了。。
注意:double进行强制类型转换的时候一定要注意精度问题!!!!!!因为这个wa可是欲哭无泪。。
思维点在于*200转化为long long,避免了*100的产生的奇偶问题。(其实用double就能过)
代码:
#include<bits/stdc++.h>
#define ll long long
#define fi first
#define se second
#define pi acos(-1)
#define inf 0x3f3f3f3f3f3f3f3f
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define rep(i,x,n) for(int i=x;i<n;i++)
#define per(i,n,x) for(int i=n;i>=x;i--)
using namespace std;
typedef pair<ll,ll>P;
const int MAXN=100010;
int gcd(int a,int b){return b?gcd(b,a%b):a;}
ll w[40];
vector<ll>l;
vector<ll>::iterator it;
int main()
{
ll n,sum=0,SUM;
double x;
while(~scanf("%lld",&n))
{
l.clear();
sum=0;
for(int i=0;i<n;i++)
{
scanf("%lf",&x);
w[i]=x*200+0.1;//+0.1是为了解决精度问题。。
sum+=w[i];
}
SUM=sum>>1;
int len=1<<(n>>1);
for(int i=0;i<len;i++)
{
int t=i,cnt=0;
sum=0;
while(t)
{
if(t&1)sum+=w[cnt];
t>>=1;
cnt++;
}
l.push_back(sum);
}
sort(l.begin(),l.end());
len=1<<(n-(n>>1));
ll ans=inf;
for(int i=0;i<len;i++)
{
int t=i,cnt=0;
sum=0;
while(t)
{
if(t&1)sum+=w[cnt+(n>>1)];
t>>=1;
cnt++;
}
it=lower_bound(l.begin(),l.end(),SUM-sum);
if(it!=l.end())
ans=min(ans,abs(SUM-sum-(*it)));
if(it!=l.begin())
ans=min(ans,abs(SUM-sum-(*(it-1))));
}
ans<<=1;
printf("%.2f\n",ans*1.0/200);
}
return 0;
}