您的位置:首页 > 其它

poj2342—树形dp

2015-09-15 16:06 399 查看
华电北风吹

天津大学认知计算与应用重点实验室

日期: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 100

int 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=0
while 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])-1
dp=[[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]))
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: