医院设置wustOJ 二叉树中求*****

1007: 医院设置

Time Limit: 1 Sec   Memory Limit: 65535 MB   64bit IO Format: %lld
Submitted: 3   Accepted: 3
[ Submit][ Status][ Web Board]

Description

一颗二叉树有n(1≤n≤50)个结点,分别编号为1到n,每个结点代表一个居民点,每个居民点都有一定数量的居民(≤100)。现在需要选择一个居民点建一家医院,使得所有居民走的路程之和最小。同时约定,相邻两节点之间的距离为1。
例如对于样例,有5个居民点,每个居民点的居民数量分别为13,4,12,20,40.如果选择居民点1作为医院位置的话,则距离和为4*1+13*0+12*1+20*2+40*2=136;若选择居民点3的话,则距离和为4*2+13*1+12*0+20*1+40*1=81,…

Input

包含多组测试数据。每组测试数据第一行包含一个整数n,接下来的n行,每行3个数据,表示居民点i(1≤i≤n)的居民数和相邻两个居民点编号,如果编号为0表示不存在。

Output

输出最小距离和。

Sample Input 

5
13 2 3
4 0 0
12 4 5
20 0 0
40 0 0

Sample Output

81

事先说一下。。。。。。。写的好像有点烦了…………

我最近入门dp    之前好像遇到一个类似的题  当然是要难得多的  (这道题倒是没花我多少时间 

当时的题的对象是  整个图   不是树   求这么一个点   其他点到这个点的路径之和最短   真是蒙了个B了   而且数据范围我记得是100W    居然还有个煞笔让我爆搜  我×&&&%¥¥#%%#×%…………     

因为之前碰到这个题  所以我真的不愿意爆搜   所以就换一种方法写了一下

这个是树倒是容易些  但我觉得我写的烦了 

以下源码  (简单  就不注释了    如果有什么更好的方法  可以的话可以跟我说一下  除了DP…………

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <stack>

#define root tree[id]
#define leson tree[ldir]
#define rison tree[rdir]

using namespace std;
const int maxn = 60;
int n, ans;

struct node {
    int lson, rson;
    int lnum, rnum;
    int val, sum;
    int key;
};

node tree[maxn];

void FixTree(int id, int dep)
{
    int ldir = root.lson, rdir = root.rson;
    if (ldir)
        FixTree(ldir, dep + 1);
    if (rdir)
        FixTree(rdir, dep + 1);
    root.sum = leson.sum + rison.sum + root.val;
    root.lnum = leson.sum;
    root.rnum = rison.sum;
    root.key = leson.key + rison.key + leson.val * (dep + 1) + rison.val * (dep + 1);
}

void CalcTree(int id, int pre, int pre_key)
{
    int ldir = root.lson, rdir = root.rson;
    if(id!=1)
        root.key = pre_key + pre - root.lnum - root.rnum - root.val;
    if (ldir)
        CalcTree(ldir, root.rnum + root.val + pre, root.key);
    if (rdir)
        CalcTree(rdir, root.lnum + root.val + pre, root.key);
    ans=min(ans,root.key);
}

int main()
{
    tree[0].sum = 0;
    while (scanf("%d", &n) != EOF) {
        for (int id = 1; id <= n; id++) {
            scanf("%d %d %d", &root.val, &root.lson, &root.rson);
            root.sum = root.val;
        }
        for (int id = 0; id <= maxn; id++)
            root.key = 0;
        FixTree(1, 0);
        ans = tree[1].key;
        CalcTree(1, 0, tree[1].key);
        printf("%d\n", ans);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值