问题
https://vjudge.net/problem/UVA-1354
分析
参考:https://www.cnblogs.com/worldcreator-zh/p/10769859.html
能力太差了,知道是枚举二叉树,很多细节还是处理不好。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <map>
#include <string>
#include <vector>
#include <algorithm>
#include <queue>
using namespace std;
typedef long long LL;
const int maxn=6;
struct Tree{
double L,R;
Tree(double L=0,double R=0):L(L),R(R){}
};
int s,kase=0,vis[1<<maxn],w[maxn];
vector<Tree> tree[1<<maxn]; //tree[i]存储i对应的Tree结果
double r,ans,sum[1<<maxn];
//遍历subset可以构建的所有的子树,存入tree[subset中
void dfs(int subset){
if(vis[subset]) return;
vis[subset]=1;
bool have_children=false;
for(int L=(subset-1)⊂L;L=(L-1)&subset){
int R=subset^L;
have_children=true;
double d1=sum[R]/sum[subset],d2=sum[L]/sum[subset];
dfs(L);
dfs(R);
for(int i=0;i<tree[L].size();++i){
for(int j=0;j<tree[R].size();++j){
Tree t;
t.L=max(tree[L][i].L+d1,tree[R][j].L-d2);
t.R=max(tree[L][i].R-d1,tree[R][j].R+d2);
if(t.L+t.R<r) tree[subset].push_back(t);
}
}
}
//这个是必须的
if(!have_children) tree[subset].push_back(Tree());
}
int main(void){
scanf("%d",&kase);
while(kase--){
scanf("%lf%d",&r,&s);
for(int i=0;i<s;++i){
scanf("%d",&w[i]);
}
int S=1<<s;
memset(vis,0,sizeof(vis));
for(int i=0;i<S;++i){
sum[i]=0;
tree[i].clear();
for(int j=0;j<s;++j){
if(i&(1<<j)){
sum[i]+=w[j];
}
}
}
dfs(S-1);
ans=-1;
for(int i=0;i<tree[S-1].size();++i){
ans=max(ans,tree[S-1][i].L+tree[S-1][i].R);
}
printf("%.10lf\n", ans);
}
return 0;
}