P2016 战略游戏

  一道还算比较好写的“求树的最大独立集”的问题。

  f [ x ] [ 0 ] 表示以x为节点的子树上,在x位置不放士兵时,士兵数量的最小值;

  f [ x ] [ 1 ] 表示以x为节点的子树上,在x位置要放士兵时,士兵数量的最小值;

  那么方程就写出来了,在回溯的时候,对于f [ x ] [ 0 ] ,它的子节点一定都要放,累加f [ x ] [ 1 ] ;那么对于f [ x ] [ 1 ] ,取最小值就可以了。

  注意边界判断,当你到树的叶子的时候,要在操作 f 之后返回。

  代码如下:

 

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
#define maxn 2000
struct data
{
    int num,child[maxn];
} node[maxn];
int f[maxn][3],n,root;
bool vis[maxn];
void dp(int x)
{
    f[x][0]=0;
    f[x][1]=1;
    if(!node[x].num) return ;
    for(int i=1;i<=node[x].num;i++)
    {
        dp(node[x].child[i]);
        f[x][0]+=f[node[x].child[i]][1];
        f[x][1]+=min(f[node[x].child[i]][1],f[node[x].child[i]][0]);
    }
}
int main()
{
    memset(f,0x3f,sizeof(f));
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        int x,y;
        scanf("%d",&x);
        scanf("%d",&node[x].num);
        for(int j=1;j<=node[x].num;j++)
        {
            scanf("%d",&node[x].child[j]);
            vis[j]=1;
        }
    }
    while(vis[root]) root++;
    dp(root);
    printf("%d",min(f[root][0],f[root][1]));
    return 0;
}

  最后想加一句,所谓树形dp,我认为就是想方设法利用刚刚到过(并从那里回来)的点更新现在这个点,更新到最后就是答案了。

原文地址:https://www.cnblogs.com/popo-black-cat/p/10182644.html

时间: 2024-08-30 09:22:36

P2016 战略游戏的相关文章

P2016 战略游戏——树形DP大水题

P2016 战略游戏 树形DP 入门题吧(现在怎么是蓝色标签搞不懂): 注意是看见每一条边而不是每一个点(因为这里错了好几次): #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn=3010; int pre[maxn],last[maxn],other[maxn],l; void add(int x,int y) { l++; pre[l]

【Luogu】P2016战略游戏(树形DP)

题目链接 设f[i][j]表示以节点i为根的子树在状态j的情况下的最优解. j有两种情况. j=1:i这个根节点有士兵在站岗. j=0:i这个根节点没有士兵在站岗. 转移方程很好想. f[x][1]+=min(f[to][0],f[to][1]); f[x][0]+=f[to][1]; 这样子. 意思就是:如果根节点已经有人站岗了,那么它的直接子节点可站可不站.就从子节点的两种状态中选一个小的. 如果根节点没有人站岗,那它的所有直接子节点都必须站岗,否则会有道路有人看不到. 代码奉上. #inc

luogu#P2016 战略游戏

题意: 给出一棵有 \(N\) 个节点的树,节点编号 \(0\) ~ \(N-1\) .如果在一个节点上放置一个士兵,那么该节点及与该节点相连的所有节点都可以被瞭望到.求瞭望到所有节点所需的最少的士兵数. 解法: 树形dp 设 \(f[i][j]\) = 节点 \(i\) 选(\(j=1\))不选(\(j=0\))的最少需要的士兵 因为对于一个节点 \(i\) ,如果它不选,那么必须选与它相连的点的其中一个,则: f[x][1]+=min(f[v][0],f[v][1]); //设v是与x相邻的

luogu P2016 战略游戏 树形dp

#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int N=3010; int e[N],h[N],ne[N],idx; int f[N][2]; bool st[N]; void add(int a,int b) { e[idx]=b; ne[idx]=h[a]; h[a]=idx++; } int n,

Facebook开源游戏平台ELF: 一个用于实时战略游戏研究的轻量级平台

ELF是一个用于游戏研究的应用广泛的(Extensive).轻量级的(Lightweight).灵活的(Flexible)平台,特别适用于实时战略(RTS)游戏.在C++方面,ELF采用C++线程来并发运行多个游戏.在Python方面,ELF可以一次性返回一批游戏状态,使其对现代RL(强化学习)非常友好.另一方面,在其他平台(例如OpenAI Gym)中,一个Python接口只能包含一个游戏实例.这使得游戏的并发运行有点复杂,而这又是许多现代强化学习算法的要求. 对于RTS游戏的研究,ELF配备

战略游戏

题意/Description: Bob喜欢玩电脑游戏,特别是战略游戏.但是他经常无法找到快速玩过游戏的办法.现在他有个问题.他要建立一个古城堡,城堡中的路形成一棵树.他要在这棵树的结点上放置最少数目的士兵,使得这些士兵能了望到所有的路.注意,某个士兵在一个结点上时,与该结点相连的所有边将都可以被了望到.  请你编一程序,给定一树,帮Bob计算出他需要放置最少的士兵. 读入/Input:    输入文件中数据表示一棵树,描述如下: 第一行 N,表示树中结点的数目. 第二行至第N+1行,每行描述每个

bzoj3924 [Zjoi2015]幻想乡战略游戏 点分树,动态点分

[BZOJ3924][Zjoi2015]幻想乡战略游戏 Description 傲娇少女幽香正在玩一个非常有趣的战略类游戏,本来这个游戏的地图其实还不算太大,幽香还能管得过来,但是不知道为什么现在的网游厂商把游戏的地图越做越大,以至于幽香一眼根本看不过来,更别说和别人打仗了. 在打仗之前,幽香现在面临一个非常基本的管理问题需要解决. 整个地图是一个树结构,一共有n块空地,这些空地被n-1条带权边连接起来,使得每两个点之间有一条唯一的路径将它们连接起来.在游戏中,幽香可能在空地上增加或者减少一些军

【BZOJ3924】幻想乡战略游戏(动态点分治)

[BZOJ3924]幻想乡战略游戏(动态点分治) 题面 权限题...(穷死我了) 洛谷 题解 考虑不修改 发现一个贪心的做法 假设当前放在当前位置 如果它有一个子树的兵的总数大于总数的一半 那么,放到那个子树的根节点上一定最优 那么,现在是动态修改 考虑动态点分治 在每个点上维护子树的兵的总数 子树到上一层父亲节点 向上走产生的贡献的总和 以及接收到子节点的贡献的总和 那么,就可以计算当前点产生的贡献 于是,从分治树根开始向下贪心即可 #include<iostream> #include&l

bzoj 5329 [SDOI2018] 战略游戏

bzoj 5329 [SDOI2018] 战略游戏 Link Solution 很容易想到虚树 然后发现是一个图... 现学圆方树,套上去,做完了(模板题?) 就是直接上广义圆方树先把这玩意转换成一棵树,然后对当前询问建立虚树,断掉虚树里任何一个点都合法(包括不出现的点,指那些在某个点和其虚树上父亲之间的点),统计一下即可 Code // Copyright lzt #include<stdio.h> #include<cstring> #include<cstdlib>