323. 战略游戏

题目链接

323. 战略游戏

鲍勃喜欢玩电脑游戏,特别是战略游戏,但有时他找不到解决问题的方法,这让他很伤心。

现在他有以下问题。

他必须保护一座中世纪城市,这条城市的道路构成了一棵树。

每个节点上的士兵可以观察到所有和这个点相连的边。

他必须在节点上放置最少数量的士兵,以便他们可以观察到所有的边。

你能帮助他吗?

例如,下面的树:

image

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

输入格式

输入包含多组测试数据,每组测试数据用以描述一棵树。

对于每组测试数据,第一行包含整数 N,表示树的节点数目。

接下来 N 行,每行按如下方法描述一个节点。

节点编号:(子节点数目) 子节点 子节点 …

节点编号从 0N1,每个节点的子节点数量均不超过 10,每个边在输入数据中只出现一次。

输出格式

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

数据范围

0<N1500,
一个测试点所有 N 相加之和不超过 300650

输入样例:

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

解题思路

树形dp

  • 状态表示:

    • f[u][0] 表示没有选择 u 节点这棵以 u 为根节点的子树放置士兵的最少数量
    • f[u][1] 表示选择 u 节点这棵以 u 为根节点的子树放置士兵的最少数量
  • 状态计算:

    • f[u][0]=f[v][1]
    • f[u][1]=1+min(f[v][0],f[v][1]

分析:如果当前节点没有选,则其子节点必须要选,否则连向子节点的这条边不合题意;如果当前节点选了,则子节点可选可不选,取较小的即可

  • 时间复杂度:O(n)

代码

// Problem: 战略游戏 // Contest: AcWing // URL: https://www.acwing.com/problem/content/description/325/ // Memory Limit: 10 MB // Time Limit: 1000 ms // // Powered by CP Editor (https://cpeditor.org) // %%%Skyqwq #include <bits/stdc++.h> //#define int long long #define help {cin.tie(NULL); cout.tie(NULL);} #define pb push_back #define fi first #define se second #define mkp make_pair using namespace std; typedef long long LL; typedef pair<int, int> PII; typedef pair<LL, LL> PLL; template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; } template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; } template <typename T> void inline read(T &x) { int f = 1; x = 0; char s = getchar(); while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); } while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar(); x *= f; } const int N=1510; int n,f[N][2]; bool v[N]; vector<int> adj[N]; void dp(int x) { f[x][0]=0,f[x][1]=1; for(int y:adj[x]) { dp(y); f[x][0]+=f[y][1]; f[x][1]+=min(f[y][0],f[y][1]); } } int main() { while(~scanf("%d",&n)) { memset(v,0,sizeof v); for(int i=0;i<n;i++)adj[i].clear(); int x,s,y; for(int i=0;i<n;i++) { scanf("%d:(%d)",&x,&s); while(s--) { scanf("%d",&y); adj[x].pb(y); v[y]=true; } } int root=0; while(v[root])root++; dp(root); printf("%d\n",min(f[root][0],f[root][1])); } return 0; }

__EOF__

本文作者acwing_zyy
本文链接https://www.cnblogs.com/zyyun/p/16021536.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   zyy2001  阅读(73)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示