您的位置:首页 > 其它

例题7-7 UVA 1354 Mobile Computing (搜索+二叉树(类哈夫曼树))

2017-01-22 16:17 375 查看
思路:

想一想就可以知道,一个结点要么有两个儿子,要么没儿子。

那么这就很像哈夫曼树,因此我们可以枚举所有的哈夫曼树(任意枚举两个不同的结点来合并)

然后从根结点开始遍历二叉树,在遍历的同时,来枚举左边 和右边的最大值。

然后R-L 便是这个二叉树的宽度。

更新一下答案即可!

有一个小小的坑把,没注意到:

就是只有一个砝码的时候,答案应该是0 不是-1.

想一想还是很实际的:

只有一个砝码,直接拿个绳子吊起来就行了,题目中说 不考虑砝码的宽度,那么不就是0了吗!!

详细见代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
#include <cstdlib>
#define Siz(x) (int)x.size()
using namespace std;
const double eps = 1e-10;
int dcmp(double a,double b){
if (fabs(a-b) < eps) return 0;
if (a < b) return -1;
return 1;
}
struct Node{
int v;
int ban;
Node* left;
Node* right;
Node(int v = 0,int ban = 0):v(v),ban(ban){
left = right = NULL;
}
};
int T, n;
double r;
double L,R,ans;
vector<Node*>v;
void dfs2(Node* cur,double dis){
if (cur->left == NULL || cur->right == NULL) return;
int lv = cur->left->v;
int rv = cur->right->v;
double k = rv*1.0/lv;
double a = k/(1+k);
double b = 1.0/(1+k);
double nl = dis - a;
double nr = dis + b;
if (dcmp(L,nl) == 1) L = nl;
if (dcmp(R,nr) == -1) R = nr;
dfs2(cur->left,nl);
dfs2(cur->right,nr);
}

void dfs(int siz){
// printf("%d\n",siz);
if(siz > 1){
for (int i = 0; i < Siz(v); ++i){
for (int j = 0; j < i; ++j){
if (i != j){
// printf("%d %d\n",i,j);
Node* ii = v[i];
Node* jj = v[j];
v.erase(v.begin()+i);
v.erase(v.begin()+j);
// puts("hahahaha");
Node* kk = new Node(ii->v + jj->v);
kk->ban = 1;
kk->left = new Node();
kk->right = new Node();
kk->left = ii;
kk->right = jj;
v.push_back(kk);
dfs(siz-1);
v.pop_back();
kk = new Node(ii->v + jj->v);
kk->ban = 1;
kk->left = new Node();
kk->right = new Node();
kk->left = jj;
kk->right = ii;
v.push_back(kk);
dfs(siz-1);
v.pop_back();
if (j >= Siz(v))v.push_back(jj);
else v.insert(v.begin()+j,jj);
if (i >= Siz(v))v.push_back(ii);
else v.insert(v.begin()+i,ii);
}
}
}
}
else {
// puts("ahahah");
Node* root = new Node();
root = *(v.begin());
// printf("%d\n",root->v);
L = 1e18;
R = -1e18;
dfs2(root,0);
double nnr = R-L;
if (dcmp(nnr,r) != 1){
// ans = max(ans,nnr);
if (dcmp(ans,nnr) == -1) ans = nnr;
}
}
}
int main(){
scanf("%d",&T);
while(T--){
v.clear();
ans = -1e18;
scanf("%lf%d",&r,&n);
for (int i = 0; i < n; ++i) {
int vv;
scanf("%d",&vv);
v.push_back(new Node(vv,0));
}
dfs((int)v.size());
if(n == 1) puts("0"); /// 要格外注意,一个砝码的时候 宽度是0,不是-1.
else if (ans == -1e18) puts("-1");
else printf("%.16f\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: