poj1463(树形dp)

本文介绍了一种使用树形动态规划方法解决在树结构中放置最少士兵以覆盖所有边的问题。通过分析节点放置士兵的状态转移方程,给出了详细的AC代码实现,展示了如何在每个节点上决定是否放置士兵,以达到全局最小化的解决方案。

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

刚简单了学习了一下树形dp,我们再来做一道题联系一下吧,

poj1463

题意:大致意思就是现在给你一个树,然后让你再每个节点上放士兵,每个节点的士兵都可以管辖与这个节点相连的所有的边,让你放置最小的士兵来使这个树的每条边都可以被管辖,求最小放置的士兵数。

思路:这个题大致一看就是一个dp,又是因为这是一个树。所以就是树形dp了,(这样解释是不是有点那个啥啊,哈哈)

首先我们先找状态转移方程好一个节点,假如这个节点不放士兵,那么他的孩子每个都要放置士兵,只有这样才能满足要求,再假入,这个点放置了士兵,那么他的孩子的士兵就可放可不放了,根据这个思想我们就可以列出状态转移方程,dp[root][0] += dp[i][1];    dp[root][1] += min(dp[i][0], dp[i][1]);

下面直接给出AC代码;

#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
const int maxn=1600;
#define met(a,A) memset(a,A,sizeof(a))
int dp[maxn][2],father[maxn];
bool vis[maxn];
int n;
void void_tree(int root)
{
    vis[root]=1;
    for(int i=1;i<=n;i++)
    {
        if(!vis[i]&&father[i]==root)
        {
            void_tree(i);
            dp[root][0] += dp[i][1];
            dp[root][1] += min(dp[i][0], dp[i][1]);
        }
    }
}
int main()
{
    while(~scanf("%d",&n))
    {
        met(dp,0);
        met(father,0);
        met(vis,0);
        for(int i=1;i<=n;i++)
            dp[i][1]=1;

        for(int i=0;i<n;i++)
        {
            int nn,nnn;
            scanf("%d:(%d)",&nn,&nnn);
            nn++;
            while(nnn--)
            {
                int A;
                scanf("%d",&A);
                A++;
                father[A]=nn;
            }
        }
        void_tree(0);
        printf("%d\n",min(dp[0][1],dp[0][0]));
    }

    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值