hdu 1054
Posted xxrlz
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu 1054相关的知识,希望对你有一定的参考价值。
这是一道树形dp的题 最近有点想学dp但各种高深操作还是学不来
题目大意是给你一颗树,在树的节点上放置士兵,需要用最少的士兵来沾满所有的边.
由于每个节点只有放士兵和不放士兵两个状态且子节点的来源与当前节点没有关系,(儿子的儿子放不放并不影响父亲)就满足了dp的条件吧
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int MAXN = 1510;
int vis[MAXN];
struct node
{
int bro,child;
int fa;
}Node[MAXN];
int dp[MAXN][2];
void DFS(int x)//dfs更新
{
int child = Node[x].child;
while(child)
{
DFS(child);//优先更新孩子
dp[x][1] +=min(dp[child][1],dp[child][0]); //利用孩子更新当前dp值
dp[x][0] += dp[child][1];
child = Node[child].bro; //遍历所有孩子
}
}
int main()
{
int n;
int root,k,v;
while(cin >> n)
{
memset(vis,0,sizeof(vis));
int Root; //树根
for(int i=0;i<n;++i)
{
scanf("%d:(%d)",&root,&k);
root++;
if(i==0) Root = root;
if(!vis[root]) //对于新加入的节点 以该节点建立新树
{
vis[root] = true;
Node[root].bro = Node[root].fa = Node[root].child = 0;
dp[root][1] =1;
dp[root][0] = 0;
}
while(k--)
{
scanf("%d",&v);
v++;
if(!vis[v]) //该节点肯定是当前树的叶子
{
vis[v] = true;
dp[v][1] = 1;
dp[v][0] = 0;
}
Node[v].bro=Node[root].child;//更新祖先和兄弟
Node[v].fa = root;
Node[root].child = v;
Node[v].child = 0;
}
}
DFS(Root);
printf("%d
",min(dp[Root][1],dp[Root][0]));
}
return 0;
}
状态方程:
[dp[i][0] = sum_{jin i.child}dp[j][1] ]
[dp[i][1] = sum_{jin i.child} min(dp[j][1],dp[j][0])]
当前节点不选 则所以孩子都得选,
当前节点选了 则孩子节点选不选都行.
叶子节点:
dp[i][0] = 0 dp[1][1] = 1
以上是关于hdu 1054的主要内容,如果未能解决你的问题,请参考以下文章