战略游戏(题解 树形DP)

蒟蒻第一次写树形DP……

有的没的


在树形DP中,我们一般以节点从深到浅(子树从小到大)的顺序作为DP的“阶段”。

大多时候,我们采用递归的方式实现树形DP,对于每个节点x,我们先递归他的子节点,在回溯时,再从子节点向节点x进行转移。

我们来看看这道超水的树形DP

题目描述


Bob喜欢玩电脑游戏,特别是战略游戏。但是他经常无法找到快速玩过游戏的办法。现在他有个问题。他要建立一个古城堡,城堡中的路形成一棵树。他要在这棵树的结点上放置最少数目的士兵,使得这些士兵能了望到所有的路。注意,某个士兵在一个结点上时,与该结点相连的所有边将都可以被了望到。

请你编一程序,给定一树,帮Bob计算出他需要放置最少的士兵。

输入格式


输入文件中数据表示一棵树,描述如下: 第一行 N,表示树中结点的数目。 第二行至第N+1行,每行描述每个结点信息,依次为:该结点标号i,k(后面有k条边与结点I相连),接下来k个数,分别是每条边的另一个结点标号r1,r2,…,rk。 对于一个n(0

输出格式


输出文件仅包含一个数,为所求的最少的士兵数目。

样例数据


input
4
0 1 1
1 2 2 3
2 0
3 0

output

1

Solution


f[i][0/1] f [ i ] [ 0 / 1 ] 表示是否选i这个节点最少的士兵人数

 //By Bibi
///                 .-~~~~~~~~~-._       _.-~~~~~~~~~-.
///             __.'              ~.   .~              `.__
///           .'//                  \./                  \\`.
///        .'//                     |                     \\`.
///       .'// .-~"""""""~~~~-._     |     _,-~~~~"""""""~-. \\`.
///     .'//.-"                 `-.  |  .-'                 "-.\\`.
///   .'//______.============-..   \ | /   ..-============.______\\`.
/// .'______________________________\|/______________________________`.
#include
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define dep(i,a,b) for(int i=a;i>=b;--i)
using namespace std;
const int MAXN=1501;
int inline read(){
    int sum=0,flag=1;
    char c;
    for(;c<'0'||c>'9';c=getchar())if(c=='-') flag=-1;
    for(;c>='0'&&c<='9';c=getchar())sum=(sum<<1)+(sum<<3)+c-'0';
    return sum*flag;
}
int n;
struct edge{
    int y,next;
}e[MAXN<<1];
int f[MAXN][2];
int link[MAXN];
int tot;
int num[MAXN];
void inline insert(int x,int y){
    e[++tot].y=y;e[tot].next=link[x];link[x]=tot;
}
void inline init(){
    n=read();
    int x,y;
    rep(i,1,n){
        x=read();
        num[x]=read();
        rep(j,1,num[x]){
            y=read();
            insert(x,y);
            insert(y,x);
        }
    }
}
void inline DP(int x,int fa){
    f[x][1]=1;
    for(int i=link[x];i;i=e[i].next){
        int y=e[i].y;
        if(y==fa) continue;
        DP(y,x);
        f[x][0]+=f[y][1];
        f[x][1]+=min(f[y][0],f[y][1]);
    }
}
int main(){
    init();
    DP(0,-1);
    printf("%d",min(f[0][0],f[0][1]));
    return 0;
}

你可能感兴趣的:(动态规划(DP))