刷题记录:牛客NC51222Strategic game

传送门:牛客

题目描述:

Bob enjoys playing computer games, especially strategic games, but sometimes he cannot find the 
solution fast enough and then he is very sad. Now he has the following problem. He must defend a 
medieval city, the roads of which form a tree. He has to put the minimum number of soldiers on the 
nodes so that they can observe all the edges. Can you help him? 
Your program should find the minimum number of soldiers that Bob has to put for a given tree. 
For example for the tree: 
the solution is one soldier ( at the node 1).
输入:
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的题目

主要思路:

  1. 对于这道题,我们使用 d p [ u ] [ 0 / 1 ] dp[u][0/1] dp[u][0/1]分别表示当前的节点放置士兵 / / /不放置士兵的最少士兵数.
  2. 那么我们很容易就能想到转移方程,对于当前结点,假设我放置士兵的话,那么对于它的儿子来说它可以放士兵,也可以不放士兵,即

d p [ u ] [ 0 ] + = m i n ( d p [ v ] [ 0 ] , d p [ v ] [ 1 ] ) dp[u][0]+=min(dp[v][0],dp[v][1]) dp[u][0]+=min(dp[v][0],dp[v][1])

  1. 对于当前结点,假设我不放置士兵的话,那么对于它的儿子来说,每一个儿子都需要放置士兵,不然的话就无法管理那一条路了.即

d p [ u ] [ 1 ] + = d p [ v ] [ 0 ] dp[u][1]+=dp[v][0] dp[u][1]+=dp[v][0]

然后这道题就巧妙的解决了

下面是具体的代码部分:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
typedef long long ll;
#define inf 0x3f3f3f3f
#define root 1,n,1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
inline ll read() {
	ll x=0,w=1;char ch=getchar();
	for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') w=-1;
	for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';
	return x*w;
}
#define maxn 1000000
#define ll_maxn 0x3f3f3f3f3f3f3f3f
const double eps=1e-8;
int n;int dp[maxn][4];
vector<int>edge[maxn];
void dfs(int u,int pre_u) {
	dp[u][0]=1;
	for(int i=0;i<edge[u].size();i++) {
		int v=edge[u][i];
		if(v==pre_u) continue;
		dfs(v,u);
		dp[u][0]+=min(dp[v][0],dp[v][1]);
		dp[u][1]+=dp[v][0];
	}
	return ;
}
int main() {
	while(scanf("%d",&n)!=EOF) {
		memset(dp,0,sizeof(dp));
		for(int i=0;i<=n;i++) edge[i].clear();
		int u,v,num;
		for(int i=1;i<=n;i++) {
			scanf("%d:(%d)",&u,&num);
			for(int j=1;j<=num;j++) {
				v=read();
				edge[u].push_back(v);
				edge[v].push_back(u);
			}
		}
		dfs(0,-1);
		cout<<min(dp[0][1],dp[0][0])<<endl;
	}
	return 0;
}

你可能感兴趣的:(c++算法,算法,动态规划,树形dp,c++)