【树形DP】ZOJ - 3949 Edge to the Root

本文介绍了一种使用树形动态规划解决特定树结构中最短距离问题的方法。通过连边变化来计算从树的根节点到其它节点的最短路径总和,详细解释了算法流程,并给出了完整的C++实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Step1 Problem:

给出一颗根为 1 的树,每条边边长为 1,请你从根连一条边到某个点,使得根到各点距离的总和最小,求这个最小距离。
数据范围:
1<=n<=2e5

Step2 Involving:

树形DP

Step3 Ideas:

假设 1 到 x 连边,受影响的只有 1 和 x 中点往下的点。
例如:一条链长度为 n,给它们按顺序 1 到 n 编号,1 和 n 连边,受影响的只有 (1+n)/2+1 点和往下的点,我们称 (1+n)/2+1 为 1 到 n 的中点
我们需要求 1 和其他所有点连边的 距离和变化值,然后求变化值最大。
假设 u 是 f 的孩子。
我们从 1 和 u 连边,变化到 1 和 f 连边
f 子树所有结点 距离都减少了 1
1 到 f 的中点子树所有结点 距离都增加了1( f 子树所有结点除外)
那么我们只要预处理出,每个子树的孩子数 siz[]。
1 和 u 连边变化量为 now
1 和 f 连边变化量为 now - siz[st[cnt]] + (siz[st[(cnt+1)/2 + 1]] - siz[st[cnt]]);// st[i] 是 i 编号对应的那个结点

Step4 Code:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 2e5+100;
const int inf = 0x3f3f3f3f;
vector<int> Map[N];
int head[N], cnt;
int siz[N], dep[N], st[N];
ll ans;
void dfs1(int u, int f)//预处理出子树孩子数(包括自身),求出最大距离
{
    siz[u] = 1; dep[u] = dep[f] + 1;
    ans += dep[u];
    for(int i = 0; i < Map[u].size(); i++)
    {
        int to = Map[u][i];
        if(to != f)
        {
            dfs1(to, u);
            siz[u] += siz[to];
        }
    }
}
ll Min;
void dfs2(int u, int f, ll now)//求出最大变化量
{
    st[++cnt] = u;
    ll now1 = now;
    if(cnt > 2)
    {
        now1 = now - siz[st[cnt]] + (siz[st[(cnt+1)/2 + 1]] - siz[st[cnt]]);
        Min = min(Min, now1);
    }
    for(int i = 0; i < Map[u].size(); i++)
    {
        int to = Map[u][i];
        if(to != f)
        {
            dfs2(to, u, now1);
            cnt--;
        }
    }
}
int main()
{
    int T, n, u, v;
    cin >> T;
    while(T--)
    {
        scanf("%d", &n);
        for(int i = 1; i <= n; i++) Map[i].clear();
        memset(head, -1, sizeof(head));
        cnt = 0;
        for(int i = 1; i < n; i++)
        {
            scanf("%d %d", &u, &v);
            Map[u].push_back(v);
            Map[v].push_back(u);
        }
        dep[0] = -1; cnt = ans = Min = 0;
        dfs1(1, 0);
        dfs2(1, 0, 0);
        cout << ans+Min << endl;
    }
    return 0;
}
资源下载链接为: https://pan.quark.cn/s/67c535f75d4c 在机器人技术中,轨迹规划是实现机器人从一个位置平稳高效移动到另一个位置的核心环节。本资源提供了一套基于 MATLAB 的机器人轨迹规划程序,涵盖了关节空间和笛卡尔空间两种规划方式。MATLAB 是一种强大的数值计算与可视化工具,凭借其灵活易用的特点,常被用于机器人控制算法的开发与仿真。 关节空间轨迹规划主要关注机器人各关节角度的变化,生成从初始配置到目标配置的连续路径。其关键知识点包括: 关节变量:指机器人各关节的旋转角度或伸缩长度。 运动学逆解:通过数学方法从末端执行器的目标位置反推关节变量。 路径平滑:确保关节变量轨迹连续且无抖动,常用方法有 S 型曲线拟合、多项式插值等。 速度和加速度限制:考虑关节的实际物理限制,确保轨迹在允许的动态范围内。 碰撞避免:在规划过程中避免关节与其他物体发生碰撞。 笛卡尔空间轨迹规划直接处理机器人末端执行器在工作空间中的位置和姿态变化,涉及以下内容: 工作空间:机器人可到达的所有三维空间点的集合。 路径规划:在工作空间中找到一条从起点到终点的无碰撞路径。 障碍物表示:采用二维或三维网格、Voronoi 图、Octree 等数据结构表示工作空间中的障碍物。 轨迹生成:通过样条曲线、直线插值等方法生成平滑路径。 实时更新:在规划过程中实时检测并避开新出现的障碍物。 在 MATLAB 中实现上述规划方法,可以借助其内置函数和工具箱: 优化工具箱:用于解决运动学逆解和路径规划中的优化问题。 Simulink:可视化建模环境,适合构建和仿真复杂的控制系统。 ODE 求解器:如 ode45,用于求解机器人动力学方程和轨迹执行过程中的运动学问题。 在实际应用中,通常会结合关节空间和笛卡尔空间的规划方法。先在关节空间生成平滑轨迹,再通过运动学正解将关节轨迹转换为笛卡
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值