洛谷P2016战略游戏

传送门啦

战略游戏这个题和保安站岗很像,这个题更简单,这个题求的是士兵人数,而保安站岗需要求最优价值。

定义状态$ f[u][0/1] $ 表示 $ u $ 这个节点不放/放士兵

根据题意,如果当前节点不放置士兵,那么它的子节点必须全部放置士兵,因为要满足士兵可以看到所有的边,所以
$ f[u][0]+=f[v][1] $ ,其中$ v $ 是 $ u $ 的子节点

如果当前节点放置士兵,它的子节点选不选已经不重要了(因为树形dp自下而上更新,上面的节点不需要考虑),所以
$ f[u][1]+=min(f[v][0],f[v][1]) $

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 1505;

inline int read(){
	char ch = getchar();
	int f = 1 , x = 0;
	while(ch > '9' || ch < '0'){if(ch == '-')f = -1; ch = getchar();}
	while(ch >= '0' && ch <= '9'){x = (x << 1) + (x << 3) + ch - '0';ch = getchar();}
	return x * f;
}

int n,flag,k,x;
int head[maxn],tot;
int f[maxn][5];

struct Edge{
	int from,to,next;
}edge[maxn << 1];

void add(int u,int v){
	edge[++tot].from = u;
	edge[tot].to = v;
	edge[tot].next = head[u];
	head[u] = tot;
}

void dfs(int u,int fa) {
    f[u][1] = 1 , f[u][0] = 0;
    for(int i=head[u];i;i=edge[i].next) {
    	int v = edge[i].to;
        if(v != fa) {
        	dfs(v , u);
        	f[u][0] += f[v][1];
        	f[u][1] += min(f[v][1] , f[v][0]);
        }
    }
}

int main(){
	n = read();
	for(int i=0;i<=n-1;i++){
		flag = read(); k = read();
		if(k == 0)continue;
		for(int i=1;i<=k;i++){
			x = read();
			add(flag , x);  add(x , flag);
		}
	}
	dfs(0 , -1);
	printf("%d
",min(f[0][1] , f[0][0]));
	return 0;
}
顺风不浪,逆风不怂。
原文地址:https://www.cnblogs.com/Stephen-F/p/9882821.html