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相邻的点
f[x][0]+=f[v][1];

因为没有给出树根,所以要手动求出。

感觉跟没有舞会的上司差不多,居然还是一道蓝题

#include<iostream>
#define N 1505
using namespace std;
struct Edge{int next,to;}edge[N<<1];
int n_e,head[N],n,root;
int f[N][2];
bool rt[N];

void dp(int x);
void addedge(int from,int to);
void init();
int main()
{
    init();
    dp(root);
    cout<<min(f[root][1],f[root][0]);

    return 0;
}
void init()
{
    cin>>n;
    for(int i=0;i<n;i++)
    {
        int id,num,v;
        cin>>id>>num;
        f[i][1]=1;
        for(int j=0;j<num;j++)
        {
            cin>>v;
            rt[v]=1;
            addedge(id,v);
        }
    }
    for(int i=0;i<n;i++)
        if(!rt[i])
        {
            root=i;
            break;
        }
}
void addedge(int from,int to)
{
    edge[++n_e].next=head[from];
    edge[n_e].to=to;
    head[from]=n_e;
}
void dp(int x)
{
    for(int i=head[x];i;i=edge[i].next)
    {
        int v=edge[i].to;
        dp(v);
        f[x][1]+=min(f[v][1],f[v][0]);
        f[x][0]+=f[v][1];
    }
}

原文地址:https://www.cnblogs.com/nenT/p/11716605.html

时间: 2024-10-12 07:13:51

luogu#P2016 战略游戏的相关文章

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,

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

P2016 战略游戏

一道还算比较好写的"求树的最大独立集"的问题. f [ x ] [ 0 ] 表示以x为节点的子树上,在x位置不放士兵时,士兵数量的最小值: f [ x ] [ 1 ] 表示以x为节点的子树上,在x位置要放士兵时,士兵数量的最小值: 那么方程就写出来了,在回溯的时候,对于f [ x ] [ 0 ] ,它的子节点一定都要放,累加f [ x ] [ 1 ] :那么对于f [ x ] [ 1 ] ,取最小值就可以了. 注意边界判断,当你到树的叶子的时候,要在操作 f 之后返回. 代码如下: #

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>