poj2342—树形dp

来源:互联网 发布:java的方法的重载 编辑:程序博客网 时间:2024/04/29 19:57

华电北风吹
天津大学认知计算与应用重点实验室
日期:2015/9/15

poj上一道与动态规划特别像的题目(http://poj.org/problem?id=2342),一个公司要出席一些人员,每个人对应一个活跃度,要求是不能存在直属关系,活跃度最大。参考了别人的博客,很多人说这个是树形动态规划,我个人感觉应该划分到分治法里面(不存在重叠子问题)。
下面是我修改后的代码,采用递归的思路。例如计算根节点的最大活跃度,需要判断根节点的每一个子节点,根节点出席的话就把子节点不出席时候的活跃度相加,如果根节点不出席,就把所有根节点出席和不出席中活跃度最大的加起来,依次递归。其中,leader保存每个节点的直属leader,dp[i][0/1] 保存当前节点子树出席和不出席的活跃度。
C++ code:

#include<iostream>#include<fstream>#include<algorithm>using namespace std;#define maxn 100int n;int dp[maxn][2], leader[maxn];                         //dp[i][0]0表示不去,dp[i][1]1表示去了void tree_dp(int node){    int i;    for (i = 1; i <= n; i++)    {        if (leader[i] == node)          //i为下属        {            tree_dp(i);                                //递归调用孩子结点,从叶子结点开始dp            dp[node][1] += dp[i][0];                   //上司来,下属不来            dp[node][0] += max(dp[i][1], dp[i][0]);    //上司不来,下属来、不来        }    }}int main(){    ifstream in("C:\\Users\\zhengyi\\Desktop\\ConsoleApplication1\\input.txt");    cin.rdbuf(in.rdbuf());    int i;    int f, c, root;    while (cin>>n)    {        memset(dp, 0, sizeof(dp));        memset(leader, 0, sizeof(leader));        for (i = 1; i <= n; i++)        {            cin>>dp[i][1];        }        while (cin>>c>>f, c || f)        {            leader[c] = f;            root = f;        }        while (leader[root])                       //查找父结点            root = leader[root];        tree_dp(root);        int imax = max(dp[root][0], dp[root][1]);        printf("%d\n", imax);    }    system("pause");    return 0;}

python code:

file=open('datahdu1520.txt','r')line=file.readline()N=int(line.strip('\n'))activity=[int(file.readline().strip('\n')) for i in range(N)]leader=[i for i in range(N)]root=0while True:    line=file.readline()    if line=="0 0":        break    line=line.split()    leader[int(line[0])-1]=int(line[1])-1    root=int(line[1])-1dp=[[0 for col in range(2)] for row in range(N)]def func(person):    dp[person][0]=0    dp[person][1]=activity[person]    for i in range(N):        if leader[i]==person and i!=person:            func(i)            dp[person][0]=dp[person][0]+max(dp[i])            dp[person][1]=dp[person][1]+dp[i][0]while leader[root]!=root:    root=leader[root]func(root)print(max(dp[root]))
0 0
原创粉丝点击