如题:http://poj.org/problem?id=1463
题目要求在一棵树的节点上放士兵,士兵可以监视到周围的节点,求监视整棵树要放的最少的士兵的个数。
分析,每一个节点有2中放法,分别是放或不放。如果不放,那么它的儿子节点必须放。如果放,他的儿子可以放或不放,所以它取放或不放中最少的那个,当遇到叶子节点i,dp【i】【1】=1;dp【i】【0】=0;也就是dp[i][1]=sum(min(dp[j][1,dp[j][0]));dp[i][0]=sum(dp[j][1]);
dp【i】【1】,dp【i】【0】代表当前节点放或者不放使得士兵数最小的士兵的个数。
#include<iostream>
using namespace std;
#define N 1505
int tree[N];
int father[N];
int root;
int dp[N][2];
int M;
int min(int x,int y)
{return x>y?y:x;}
void BFS(int root)
{
int dp1=0,dp0=0;
if(tree[root]==0)
{
dp[root][1]=1;
dp[root][0]=0;
return;
}
int i;
for(i=0;i<M;i++)
{
if(father[i]==root)
{
BFS(i);
dp1+=min(dp[i][0],dp[i][1]);
dp0+=dp[i][1];
}
}
dp[root][1]=dp1+1;
dp[root][0]=dp0;
}
int main()
{
int n;
int f,nchild;
int i;
int x;
//freopen("C:\\1.txt","r",stdin);
while(~scanf("%d",&n))
{
M=n;
memset(dp,0,sizeof(dp));
memset(father,-1,sizeof(father));
memset(tree,0,sizeof(tree));
root=-1;
while(n--)
{
scanf("%d:(%d)",&f,&nchild);
tree[f]=nchild;
for(i=1;i<=nchild;i++)
{
scanf("%d",&x);
father[x]=f;
if(root==-1||root==x)
root=f;
}
}
BFS(root);
printf("%d\n",min(dp[root][1],dp[root][0]));
}
}