AcWing 323:战略游戏 ← 树形DP

【题目来源】
https://www.acwing.com/problem/content/325/

【题目描述】
鲍勃喜欢玩电脑游戏,特别是战略游戏,但有时他找不到解决问题的方法,这让他很伤心。
现在他有以下问题。
他必须保护一座中世纪城市,这条城市的道路构成了一棵树。
每个节点上的士兵可以观察到所有和这个点相连的边。
他必须在节点上放置最少数量的士兵,以便他们可以观察到所有的边。
你能帮助他吗?
例如,下面的树:

只需要放置 1 名士兵(在节点 1 处),就可观察到所有的边。

【输入格式】
输入包含多组测试数据,每组测试数据用以描述一棵树。
对于每组测试数据,第一行包含整数 N,表示树的节点数目。
接下来 N 行,每行按如下方法描述一个节点。
节点编号:(子节点数目) 子节点 子节点 ...
节点编号从 0 到 N−1,每个节点的子节点数量均不超过 10,每个边在输入数据中只出现一次。

【输出格式】
对于每组测试数据,输出一个占据一行的结果,表示最少需要的士兵数。

【输入样例】
4
0:(1) 1
1:(2) 2 3
2:(0)
3:(0)
5
3:(3) 1 4 2
1:(1) 0
2:(0)
0:(0)
4:(0)

【输出样例】
1
2

【数据范围】
0<N≤1500,
一个测试点所有 N 相加之和不超过 300650。

【算法分析】
● 状态表示
fu0 表示在以 u 为根的子树中选择,并且不选 u 时的最少士兵数。
fu1 表示在以 u 为根的子树中选择,并且选 u 时的最少士兵数。
● 属性:min
● 状态计算(si 表示 u 的第 i 个孩子)
当前 u 不选,子节点一定要选 :fu0 = ∑fsi1
当前 u 选了,那么子节点可选可不选:fu1 = ∑min(fsi0, fsi1)

【算法代码】

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;

const int N=2e3;
const int M=N<<1;
int f[N][2];
int e[M],ne[M],h[N],idx;

void add(int a,int b) {
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}

void dfs(int u,int fa) {
    f[u][1]=1,f[u][0]=0;
    for(int i=h[u]; i!=-1; i=ne[i]) {
        int j=e[i];
        if(j==fa) continue;
        dfs(j,u);
        f[u][1]+=min(f[j][0],f[j][1]);
        f[u][0]+=f[j][1];
    }
}

int main() {
    int n;
    while(cin>>n) {
        memset(h,-1,sizeof h);
        idx=0;
        for(int i=1; i<=n; i++) {
            int a,b,m;
            scanf("%d:(%d)",&a,&m);
            while(m--) {
                cin>>b;
                add(a,b),add(b,a);
            }
        }
        dfs(1,-1);
        cout<<min(f[1][0],f[1][1])<<endl;
    }
    return 0;
}

/*
in:
4
0:(1) 1
1:(2) 2 3
2:(0)
3:(0)
5
3:(3) 1 4 2
1:(1) 0
2:(0)
0:(0)
4:(0)

out:
1
2
*/

【参考文献】
https://developer.aliyun.com/article/1039179
https://www.cnblogs.com/newblg/p/14406459.html

相关推荐
彧azz1 天前
算法设计与分析:贪心与动态规划
数据结构·学习·算法·贪心算法·动态规划
Logic1013 天前
C语言/数据结构动态规划题解:Kadane算法求最大子数组和——O(n)时间O(1)空间
c语言·数据结构·动态规划·贪心·时间复杂度·算法题·最大子数组和
梦帮科技3 天前
AI 音乐产品的发布工程:验证门、数据发布、回滚与生产运维纪律
数据结构·数据库·架构·node.js·音视频·动态规划·推荐算法
语戚3 天前
力扣 1621. 大小为K的不重叠线段的数目:动态规划(Java 实现)
java·算法·leetcode·动态规划·力扣·dp
青山木3 天前
Hot 100 --- 最长有效括号
java·数据结构·算法·leetcode·动态规划
这料鬼有毒3 天前
二刷hot100-1143.最长公共子序列
算法·leetcode·动态规划
Tisfy4 天前
LeetCode 1477.找两个和为目标值且不重叠的子数组:滑动窗口 + 记录前值(动态规划)
动态规划·题解·dp·滑动窗口
ynchyong5 天前
动态规划解题思路:入门篇
动态规划
Tisfy6 天前
LeetCode 2472.不重叠回文子字符串的最大数目:动态规划(贪心)
动态规划·字符串·题解·贪心·dp·回文字符串
青山木7 天前
Hot 100 --- 最长递增子序列
java·数据结构·算法·leetcode·动态规划