暴力枚举子集合,再求解;(暴力子集合小白上有篇幅详细介绍)
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<cmath>
using namespace std;
const int MAXN=7;
const int MAXM=1<<MAXN;
double w[MAXN],sum[MAXM],r;
bool done[MAXM];
int n;
struct node
{
double l,r;
node(double ll=0,double rr=0)
{
l=ll;r=rr;
}
};
vector<node>p[MAXM];
double min(double a,double b){return a>b?b:a;}
double max(double a,double b){return a<b?b:a;}
int bitcnt(int x)
{
if(x==0)return 0;
return bitcnt(x/2)+(x&1);
}
void dfs(int s)
{
if(done[s])return ;
done[s]=1;
if(bitcnt(s)==1)
{
p[s].push_back(node(0,0));
return ;
}
int l,i,j,k;
for(l=(s-1)&s;l>0;l=(l-1)&s)
{
int r=s^l;
dfs(l);dfs(r);
for(i=0;i<p[l].size();i++)
for(j=0;j<p[r].size();j++)
{
double xl=sum[r]/(sum[l]+sum[r]);
double xr=sum[l]/(sum[l]+sum[r]);
double ll=min(-xl+p[l][i].l,xr+p[r][j].l);
double rr=max(-xl+p[l][i].r,xr+p[r][j].r);
p[s].push_back(node(ll,rr));
}
}
}
void solve()
{
int s=(1<<n)-1;
dfs(s);
int i;double dist,ans=-1;
for(i=0;i<p[s].size();i++)
if((dist=p[s][i].r-p[s][i].l)<r&&dist>ans)ans=dist;
if(ans!=-1)printf("%.10lf\n",ans);
else printf("-1\n");
}
int main()
{
int N,i,j;
cin>>N;
while(N--)
{
scanf("%lf%d",&r,&n);
for(i=0;i<n;i++)
scanf("%lf",&w[i]);
for(i=0;i<(1<<n);i++)
{
sum[i]=0;
for(j=0;j<n;j++)
if(i&(1<<j))sum[i]+=w[j];
}
memset(done,0,sizeof done);
for(i=1;i<(1<<n);i++)
p[i].clear();
solve();
}
return 0;
}