hdu2412 树形DP

来源:互联网 发布:域名中国商标 编辑:程序博客网 时间:2024/05/22 03:43

   个人做的第一道树形DP,很经典也很有代表性。

  题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2412

  题目大致意思就是任意一个节点 i 不能与它的父亲节点 j 同时被取。问最多能去多少个节点。

  对于每个节点显然有两种状态,要么取、要么不取,所以定义dp[ 0 ][ i ] 和 dp[ 1 ][ i ]分别代表不去 i 和 取 i 所获得的 i 的子树上的最大收益。

  dp[ 0 ][ i ]=∑max(dp[ 0 ][ j ]  , dp[ 1 ][ j ])

  dp[ 1 ][ i ]=∑dp[ 0 ][ j ]

  另设dup[ 0 ][ i ] 和 dup[ 1 ][ i ]表示取法是否唯一。DP转移方程详见程序部分,其实这就特别好写了。

  

#include "iostream"#include "cstdio"#include "cstring"#include "algorithm"using namespace std;int n,c;int head[205];int dp[2][205],dup[2][205];struct NODE{    int to,next;}edge[5000];void dfs(int x){    int i,j,k;    dp[0][x]=0,dp[1][x]=1;    for(i=head[x];i!=-1;i=edge[i].next)    {        int to=edge[i].to;        dfs(to);        dp[0][x]+=max(dp[0][to],dp[1][to]);        dp[1][x]+=dp[0][to];    }    return;}void Dup(int x){    int i;    dup[0][x]=dup[1][x]=1;    for(i=head[x];i!=-1;i=edge[i].next)    {        int to=edge[i].to;        Dup(to);        if((dp[0][to] > dp[1][to] && !dup[0][to]) || (dp[1][to] > dp[0][to] && !dup[1][to]) || (dp[0][to] == dp[1][to])) dup[0][x]=0;        if(!dup[0][to]) dup[1][x]=0;    }    return;}int main(){    while(scanf("%d",&n) , n)    {        int i,j,k;        char s[205][105];        char name1[105],name2[105];        scanf("%s",s[0]);        memset(dup,0,sizeof(dup));        memset(head,-1,sizeof(head));        for(i=1,j=1,c=0; i<n; i++)        {            int p,q;            scanf("%s %s",name1,name2);            for(k=0; k<j; k++)            {                if(strcmp(name1,s[k]) == 0) break;            }            p=k;            if(k == j)            {                strcpy(s[j],name1);                j++;            }            for(k=0;k<j;k++)            {                if(strcmp(name2,s[k]) == 0) break;            }            q=k;            if(k == j)            {                strcpy(s[j],name2);                j++;            }            edge[c].to=p,edge[c].next=head[q],head[q]=c++;        }        dfs(0);        printf("%d ",max(dp[0][0],dp[1][0]));        Dup(0);        if(dp[0][0] == dp[1][0]) printf("No\n");        else if(dp[0][0] > dp[1][0])        {            if(!dup[0][0]) printf("No\n");            else printf("Yes\n");        }        else        {            if(!dup[1][0]) printf("No\n");            else printf("Yes\n");        }    }}

0 0
原创粉丝点击