Mobile Computing UVA - 1354 (枚举二叉树)
https://cn.vjudge.net/problem/UVA-1354
分析:
一个个枚举二叉树,计算每个二叉树的最大值即可,二叉树可用数组模拟。
枚举二叉树:一次拿出两个结点组成一个子数,递归n-1层即可。
要注意一种特殊情况,如图:
代码注释很详细:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1<<6;
double len, ans;
int wight[maxn], vis[maxn], n, cnt;
double lf[maxn], rg[maxn];
void dfs(int cur) {
if(cur==n-1) {//递归到n-1层
if(lf[cnt-1]+rg[cnt-1]<=len) {
ans = max(ans, lf[cnt-1]+rg[cnt-1]);
}
}
else {
for(int i = 0; i < cnt; i++) {//默认i为左,j为右
if(!vis[i]) {
for(int j = 0; j < cnt; j++) {
if(!vis[j] && i!=j) {
vis[i] = vis[j] = 1;//标记,已访问过
wight[cnt] = wight[i]+wight[j];//父结点的总权值
double ll = wight[j]*(1.0)/wight[cnt];//父结点的左长度
double rr = 1-ll;//父结点右长度
lf[cnt] = max(lf[j]-rr, ll+lf[i]);//右子树的左长度大于左子树的左长度的特殊情况
rg[cnt] = max(rg[i]-ll, rr+rg[j]);//同上
cnt++;
dfs(cur+1);
cnt--;
vis[i] = vis[j] = 0;//复原
}
}
}
}
}
}
int main() {
freopen("i.txt","r",stdin);
freopen("o.txt","w",stdout);
int m;
cin >> m;
while(m--) {
cnt = 0;
ans = -1;
memset(lf, 0, sizeof(lf));
memset(rg, 0, sizeof(rg));
memset(vis, 0, sizeof(vis));
cin >> len >> n;
for(int i = 0; i < n; i++) {
cin >> wight[i];
cnt++;
}
dfs(0);
if(ans==-1) cout << ans << endl;
else printf("%.16f\n", ans);
}
return 0;
}