首页 > 代码库 > 树形DP习题

树形DP习题

听闻noip要考树形DP,本蒟蒻万分惶恐,特刷一坨题目,以慰受惊之心。

codevs 1486

/*和非常出名的“选课”是一个题*/
#include<cstdio>
#include<iostream>
#include<cstring>
#define N 1010
using namespace std;
int son[N][2],f[N][N],v[N],n,m,flag;
int dfs(int x,int y)
{
    if(f[x][y]!=-1)return f[x][y];
    if(x==0||y<=0)
    {
        if(!flag)flag=1;
        else return 0;
    }
    f[x][y]=dfs(son[x][1],y);
    for(int i=0;i<=y-1;i++)
      f[x][y]=max(f[x][y],dfs(son[x][0],i)+dfs(son[x][1],y-1-i)+v[x]);
    return f[x][y];
}
int main()
{
    memset(f,-1,sizeof(f));
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
      scanf("%d",&v[i]);
    for(int i=1;i<=n;i++)
    {
        int x,y;scanf("%d%d",&x,&y);
        if(!son[x][0])son[x][0]=y;
        else
        {
            x=son[x][0];
            while(son[x][1])x=son[x][1];
            son[x][1]=y;
        }
    }
    printf("%d",dfs(0,m+1));
    return 0;
}

codevs 1163

#include<cstdio>
#include<iostream>
#include<cstring>
#define N 110
using namespace std;
int son[N][2],cost[N],val[N],f[N][N*6],n,m,p=1;
void build(int x)
{
    if(val[x])return;
    son[x][0]=++p;build(p);
    son[x][1]=++p;build(p);
}
int dfs(int x,int y)
{
    if(f[x][y]!=-1)return f[x][y];
    if(y<=0)return 0;
    if(val[x])return min(val[x],(y/5));
    int s0=son[x][0],s1=son[x][1];
    f[x][y]=max(dfs(s0,y-cost[s0]),dfs(s1,y-cost[s1]));
    for(int i=0;i<=y;i++)
      f[x][y]=max(f[x][y],dfs(s0,i-cost[s0])+dfs(s1,y-i-cost[s1]));
    return f[x][y];
}
int main()
{
    memset(f,-1,sizeof(f));
    scanf("%d",&m);
    int x,y;
    while(scanf("%d%d",&x,&y)!=EOF)
    {
        cost[++n]=x*2;val[n]=y;
    }
    build(1);
    printf("%d",dfs(1,m-cost[1]));
    return 0;
}

poj 1463

/*
  题意:给定一棵树,要求选最少的点,是每条边至少有一个点被选中
  f[i][0/1]表示第i个点选或不选的最少花费。
*/
#include<cstdio>
#include<iostream>
#include<cstring>
#define N 1510
using namespace std;
int head[N],f[N][2],n,cnt;
struct node
{
    int v,pre;
};node e[N*2];
void add(int x,int y)
{
    ++cnt;
    e[cnt].v=y;
    e[cnt].pre=head[x];
    head[x]=cnt;
}
void dfs(int x,int fa)
{
    f[x][1]=1;
    for(int i=head[x];i;i=e[i].pre)
    {
        if(e[i].v==fa)continue;
        dfs(e[i].v,x);
        f[x][1]+=min(f[e[i].v][0],f[e[i].v][1]);
        f[x][0]+=f[e[i].v][1];
    }
}
int main()
{
    freopen("jh.in","r",stdin);
    while(scanf("%d",&n)!=EOF)
    {
        cnt=0;
        memset(f,0,sizeof(f));
        memset(e,0,sizeof(e));
        memset(head,0,sizeof(head));
        for(int i=1;i<=n;i++)
        {
            int x,y,z;
            scanf("%d:(%d) ",&x,&y);
            for(int j=1;j<=y;j++)
            {
                scanf("%d",&z);
                add(x,z);add(z,x);
            }
        }
        dfs(0,-1);
        printf("%d\n",min(f[0][0],f[0][1]));
    }
    return 0;
}

 

树形DP习题