zoukankan      html  css  js  c++  java
  • [洛谷P2016] 战略游戏 (树形dp)

    战略游戏

    题目描述

    Bob喜欢玩电脑游戏,特别是战略游戏。但是他经常无法找到快速玩过游戏的办法。现在他有个问题。

    他要建立一个古城堡,城堡中的路形成一棵树。他要在这棵树的结点上放置最少数目的士兵,使得这些士兵能了望到所有的路。

    注意,某个士兵在一个结点上时,与该结点相连的所有边将都可以被了望到。

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

    输入输出格式

    输入格式:

    第一行 N,表示树中结点的数目。

    第二行至第N+1行,每行描述每个结点信息,依次为:该结点标号i,k(后面有k条边与结点I相连)。

    接下来k个数,分别是每条边的另一个结点标号r1,r2,...,rk。

    对于一个(n(0<n<=1500))个结点的树,结点标号在0到n-1之间,在输入数据中每条边只出现一次。

    输出格式:

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

    例如,对于如下图所示的树:

       0
    

    1 2 3

    答案为1(只要一个士兵在结点1上)。

    输入输出样例

    输入样例#1:

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

    输出样例#1:

    1

    Solution

    树形结构!!!

    因为是一棵树,所以对于每个节点,我们都把它当成根节点处理( o)树形dp!!!

    注意,某个士兵在一个结点上时,与该结点相连的所有边将都可以被了望到。

    定义状态dp[u][0/1]表示u这个节点不放/放士兵

    根据题意,如果当前节点不放置士兵,那么它的子节点必须全部放置士兵,因为要满足士兵可以看到所有的边,所以

    [dp[u][0]+=dp[to][1] ]

    其中to是u的子节点

    如果当前节点放置士兵,它的子节点选不选已经不重要了(因为树形dp自下而上,上面的节点不需要考虑),所以

    [dp[u][1]+=min(dp[to][0],dp[to][1]) ]

    Code

    #include<bits/stdc++.h>
    #define rg register
    #define il inline
    #define Min(a,b) (a)<(b)?(a):(b)
    #define Max(a,b) (a)>(b)?(a):(b)
    using namespace std;
    
    const int N=1510;
    
    void in(int &ans) {
        ans=0; char i=getchar();
        while(i<'0' || i>'9') i=getchar();
        while(i>='0' && i<='9') ans=(ans<<1)+(ans<<3)+i-'0',i=getchar();
    }
    
    int n,cur;
    
    int to[N<<1],nex[N<<1],head[N];
    int dp[N][2];
    
    il void add(int a,int b) {
        to[++cur]=b;
        nex[cur]=head[a];
        head[a]=cur;
    }
    
    il void read() {
        for(rg int i=1;i<=n;i++) {
            int x,k,y; in(x),in(k);
            for(rg int j=1;j<=k;j++) {
                in(y); add(x,y),add(y,x);
            }
        }
    }
    
    void dfs(int u,int fa) {
        dp[u][1]=1,dp[u][0]=0;
        for(rg int i=head[u];i;i=nex[i]) {
            if(to[i]==fa) continue;
            dfs(to[i],u);
            dp[u][0]+=dp[to[i]][1];
            dp[u][1]+=Min(dp[to[i]][1],dp[to[i]][0]);
        }
    }
    
    int main()
    {
        in(n); read(); dfs(0,-1);
        printf("%d
    ",Min(dp[0][0],dp[0][1]));
        return 0;
    }
    

    博主蒟蒻,随意转载.但必须附上原文链接

    http://www.cnblogs.com/real-l/

  • 相关阅读:
    PTA —— 基础编程题目集 —— 函数题 —— 61 简单输出整数 (10 分)
    PTA —— 基础编程题目集 —— 函数题 —— 61 简单输出整数 (10 分)
    练习2.13 不用库函数,写一个高效计算ln N的C函数
    练习2.13 不用库函数,写一个高效计算ln N的C函数
    练习2.13 不用库函数,写一个高效计算ln N的C函数
    迷宫问题 POJ 3984
    UVA 820 Internet Bandwidth (因特网带宽)(最大流)
    UVA 1001 Say Cheese(奶酪里的老鼠)(flod)
    UVA 11105 Semiprime Hnumbers(H半素数)
    UVA 557 Burger(汉堡)(dp+概率)
  • 原文地址:https://www.cnblogs.com/real-l/p/9620350.html
Copyright © 2011-2022 走看看