poj - 2531

题意

N个人参加party, 每个人有一个愉快值,他们之间有上司和下属的关系, 当其上司参加,则下属就不能参加(不希望有上下属同时参加,这样会扫兴的),反之上司不参加,则下属可参加可不参加,他们之间的关系可以用一个树形结构来进行表示,现在需要从这里面选一些人去参加party,使得愉快值最大化.

也是醉了, 想明白了,方程就是写不出, 参考了人家的解题报告才弄出来…(⊙﹏⊙)b

思路

dp 问题. 其核心思想是将一个大的树,划分为一个个独立的小树, 而每一个小树的根节点又是其大一点树的叶子节点.
然后在小树中求得最优解,归并到大一点的树上去, 依次往上归, 从而求出其最优解.

这里写图片描述
dp[i][0] 表示i 不参加party的时候其获得的愉快值
dp[i][1] 表示i 参加partty的时候其获得的愉快值
Sample Input 的输入能画出如下图, 由于其是树形结构, 因此我们可以划分出多个小树,如图A,B,C.

在树B(6->4, 7->4)中,我们可以推导出:
- 当4 不参加party的时候, 那么67可去可不去,而我们需要的是愉快值的最大化,因此我们需要67去和不去的最大值.
方程式如下:
dp[4][0]+= max(dp[6][0],dp[6][1]+max(dp[7][0],dp[7][1]);
- 当4 参加party, 则67 都不能参加.
方程式如下:
dp[4][1] += dp[6][0]+dp[6][0];
那么在树A中,则同理可以推导出:
5参加会议时:
dp[5][1] += dp[4][0]+dp[3][0];
5不参加会议时:
dp[5][0]+= max(dp[4][0],dp[4][1]) + max(dp[3][0], dp[3][1]);

因此我们可以得出推导方程如下:
dp[i][1] += dp[j][0];
dp[i][0] += max(dp[j][0], dp[j][1]);

//poj - 2531

import java.util.Scanner;

public class Main {

//    private static int[] happy = new int[6005];
    private static int[] father = new int[6005];
    private static int[][] dp = new int[6005][2];
    private static boolean[] bl = new boolean[60005];
    private static int N;

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
//        while (scanner.hasNext()) {
        N = scanner.nextInt();
        for (int i = 1; i <= N; i++) {
            dp[i][1] = scanner.nextInt();
        }
        int l;
        int k;
        while ((l = scanner.nextInt()) != 0 && (k = scanner.nextInt()) != 0) {
            father[l] = k;
        }
        int root = 1;
        while (father[root] != 0) {
            root = father[root];
        }
//        System.out.println("root="+root);
        dfs(root);
        System.out.println(Math.max(dp[root][0], dp[root][1]));

    }

    private static void dfs(int node) {
        bl[node] = true;
        for (int i = 1; i <= N; i++) {
            if (!bl[i] && father[i] == node) {
                dfs(i);    //递归下去求得dp[i][0]和dp[i][1]的值
                dp[node][1] += dp[i][0];
                dp[node][0] += Math.max(dp[i][0], dp[i][1]);
            }
        }
    }
//    }


}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值