我是靠谱客的博主 辛勤鸭子,最近开发中收集的这篇文章主要介绍2020ICPC南京 M.Monster Hunter,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

题目链接
题目描述
There is a rooted tree with n n n vertices and the root vertex is 1 1 1. In each vertex, there is a monster. The hit points of the monster in the i i i-th vertex is h p i hp_i hpi .

Kotori would like to kill all the monsters. The monster in the i i i-th vertex could be killed if the monster in the direct parent of the i i i-th vertex has been killed. The power needed to kill the i i i-th monster is the sum of h p i hp_i hpi and the hit points of all other living monsters who lives in a vertex j j j whose direct parent is i i i. Formally, the power equals to

h p i + ∑ the monster in vertex  j  is alive and  i  is the direct parent of  j h p j hp_i + sumlimits_{begin{array}{c}text{the monster in vertex } j text{ is alive} \ text{and } i text{ is the direct parent of } j end{array}} hp_j hpi+the monster in vertex j is aliveand i is the direct parent of jhpj

In addition, Kotori can use some magic spells. If she uses one magic spell, she can kill any monster using 0 0 0 power without any restriction. That is, she can choose a monster even if the monster in the direct parent is alive.

For each m = 0 , 1 , 2 , ⋯   , n m=0,1,2,cdots,n m=0,1,2,,n , Kotori would like to know, respectively, the minimum total power needed to kill all the monsters if she can use mm magic spells.
输入描述:
There are multiple test cases. The first line of input contains an integer T T T indicating the number of test cases. For each test case:

The first line contains an integer n n n ( 2 ≤ n ≤ 2 × 1 0 3 ) (2 le n le 2 times 10^3 ) (2n2×103), indicating the number of vertices.

The second line contains ( n − 1 ) (n-1) (n1) integers p 2 , p 3 , ⋯   , p n p_2,p_3,cdots,p_n p2,p3,,pn ( 1 ≤ p i < i ) (1 le p_i < i) (1pi<i) , where p i p_i pi means the direct parent of vertex i i i.

The third line contains nn integers h p 1 , h p 2 , ⋯   , h p n hp_1,hp_2,cdots,hp_n hp1,hp2,,hpn ( 1 ≤ h p i ≤ 1 0 9 ) (1 le hp_i le 10^9 ) (1hpi109) indicating the hit points of each monster.

It’s guaranteed that the sum of nn of all test cases will not exceed 2 × 1 0 3 2 times 10^3 2×103 .
输出描述:
For each test case output one line containing ( n + 1 ) (n+1) (n+1) integers a 0 , a 1 , ⋯   , a n a_0, a_1, cdots, a_n a0,a1,,an separated by a space, where a m a_m am indicates the minimum total power needed to kill all the monsters if Kotori can use m m m magic spells.

Please, DO NOT output extra spaces at the end of each line, otherwise your answer may be considered incorrect!
示例1
输入

3
5
1 2 3 4
1 2 3 4 5
9
1 2 3 4 3 4 6 6
8 4 9 4 4 5 2 4 1
12
1 2 2 4 5 3 4 3 8 10 11
9 1 3 5 10 10 7 3 7 9 4 9

输出

29 16 9 4 1 0
74 47 35 25 15 11 7 3 1 0
145 115 93 73 55 42 32 22 14 8 4 1 0

E因为写分类讨论卡了近两个半小时,M题思路秒出,结果因为背包生疏到比赛结束都没有调过样例(虽然调出来也是T )最终四题铜QAQ。。
首先,对于特定的咒语使用方案,power的总和也是确定的,因此考虑dp咒语使用方案。
设状态 f [ x ] [ i ] [ 0 / 1 ] f[x][i][0/1] f[x][i][0/1] 表示以 x x x 为根的子树使用 i i i 个咒语且节点 i i i 是/否被使用咒语时power和的最小值。
则状态转移方程为:
{ f [ x ] [ i ] [ 1 ] = min ⁡ ( ∑ y 0 , y 1 ∈ s o n x   ∑ i 0 + ∑ i 1 = i f [ y 0 ] [ i 0 ] [ 0 ] + f [ y 1 ] [ i 1 ] [ 1 ] + h p [ y 1 ] ) + h p [ x ] f [ x ] [ i ] [ 0 ] = min ⁡ ( ∑ y 0 , y 1 ∈ s o n x   ∑ i 0 + ∑ i 1 = i − 1 f [ y 0 ] [ i 0 ] [ 0 ] + f [ y 1 ] [ i 1 ] [ 1 ] ) left{begin{matrix} f[x][i][1] =&min(sumlimits_{y_0,y_1 in son_x sum i_0+sum i_1=i}f[y_0][i_0][0]+f[y_1][i_1][1]+hp[y_1]) +hp[x]\ f[x][i][0] =&min(sumlimits_{y_0,y_1 in son_x sum i_0+sum i_1=i-1}f[y_0][i_0][0]+f[y_1][i_1][1]) end{matrix}right. f[x][i][1]=f[x][i][0]=min(y0,y1sonx i0+i1=if[y0][i0][0]+f[y1][i1][1]+hp[y1])+hp[x]min(y0,y1sonx i0+i1=i1f[y0][i0][0]+f[y1][i1][1])
注意同样的转移方程不同的写法转移次数是不同的,具体区别看下面两份代码。
TLE代码
在这里插入图片描述

#include<bits/stdc++.h>

using namespace std;

inline int qr() {
    int f = 0, fu = 1;
    char c = getchar();
    while (c < '0' || c > '9') {
        if (c == '-')fu = -1;
        c = getchar();
    }
    while (c >= '0' && c <= '9') {
        f = (f << 3) + (f << 1) + c - 48;
        c = getchar();
    }
    return f * fu;
}

const int N = 2e3 + 10;
const long long INF = 1e18;
int head[N], ver[N], Next[N], tot;
int T, n, siz[N], hp[N];
long long f[N][N][2], g[N][2];

inline void add(int x, int y) {
    ver[++tot] = y;
    Next[tot] = head[x];
    head[x] = tot;
}

inline void init() {
    tot = 0;
    memset(head, 0, sizeof(int) * (n + 1));
    for (int i = 1; i <= n; ++i)
        for (int j = 0; j <= n; ++j)
            f[i][j][0] = f[i][j][1] = 0;
}

void dp(int x) {
    siz[x] = 1;
    if (!head[x]) {
        f[x][0][0] = INF, f[x][0][1] = hp[x];
        f[x][1][0] = 0, f[x][1][1] = INF;
        return;
    }
    for (int i = head[x]; i; i = Next[i]) {
        int y = ver[i];
        dp(y), siz[x] += siz[y];
        for (int j = 0; j <= siz[x]; ++j)g[j][1] = g[j][0] = INF;
        for (int j = 0; j <= siz[x]; ++j)
            for (int k = 0; k <= min(j, siz[y]); ++k) {
                if (j < siz[x])g[j][1] = min(g[j][1], f[x][j - k][1] + min(f[y][k][0], f[y][k][1] + hp[y]));
                if (j > k)g[j][0] = min(g[j][0], f[x][j - k][0] + min(f[y][k][0], f[y][k][1]));
            }
        for (int j = 0; j <= siz[x]; ++j)f[x][j][1] = g[j][1];
        for (int j = 0; j <= siz[x]; ++j)f[x][j][0] = g[j][0];
    }
    for (int i = 0; i <= siz[x] - 1; ++i)f[x][i][1] += hp[x];
}

int main() {
    T = qr();
    while (T--) {
        n = qr(), init();
        for (int i = 2; i <= n; ++i)add(qr(), i);
        for (int i = 1; i <= n; ++i)hp[i] = qr();
        dp(1);
        for (int i = 0; i <= n; ++i)
            printf("%lld%c", min(f[1][i][0], f[1][i][1]), i == n ? 'n' : ' ');
    }
    return 0;
}

AC代码

#include<bits/stdc++.h>

using namespace std;

inline int qr() {
    int f = 0, fu = 1;
    char c = getchar();
    while (c < '0' || c > '9') {
        if (c == '-')fu = -1;
        c = getchar();
    }
    while (c >= '0' && c <= '9') {
        f = (f << 3) + (f << 1) + c - 48;
        c = getchar();
    }
    return f * fu;
}

const int N = 2e3 + 10;
const long long INF = 1e18;
int head[N], ver[N], Next[N], tot;
int T, n, siz[N], hp[N];
long long f[N][N][2], g[N][2];

inline void add(int x, int y) {
    ver[++tot] = y;
    Next[tot] = head[x];
    head[x] = tot;
}

inline void init() {
    tot = 0;
    memset(head, 0, sizeof(int) * (n + 1));
    for (int i = 1; i <= n; ++i)
        for (int j = 0; j <= n; ++j)
            f[i][j][0] = f[i][j][1] = 0;
}


void dp(int x) {
    siz[x] = 1;
    if (!head[x]) {
        f[x][0][0] = INF, f[x][0][1] = hp[x];
        f[x][1][0] = 0, f[x][1][1] = INF;
        return;
    }
    for (int i = head[x]; i; i = Next[i]) {
        int y = ver[i];
        dp(y);
        for (int j = 0; j <= siz[x] + siz[y]; ++j)
            g[j][1] = g[j][0] = INF;
        for (int j = 0; j <= siz[x]; ++j)
            for (int k = 0; k <= siz[y]; ++k) {
                if (j + k < siz[x] + siz[y])
                    g[j + k][1] = min(g[j + k][1], f[x][j][1] + min(f[y][k][0], f[y][k][1] + hp[y]));
                if (j > 0)g[j + k][0] = min(g[j + k][0], f[x][j][0] + min(f[y][k][0], f[y][k][1]));
            }
        siz[x] += siz[y];
        for (int j = 0; j <= siz[x]; ++j)f[x][j][1] = g[j][1];
        for (int j = 0; j <= siz[x]; ++j)f[x][j][0] = g[j][0];
    }
    for (int i = 0; i <= siz[x] - 1; ++i)f[x][i][1] += hp[x];
}

int main() {
    T = qr();
    while (T--) {
        n = qr(), init();
        for (int i = 2; i <= n; ++i)add(qr(), i);
        for (int i = 1; i <= n; ++i)hp[i] = qr();
        dp(1);
        for (int i = 0; i <= n; ++i)
            printf("%lld%c", min(f[1][i][0], f[1][i][1]), i == n ? 'n' : ' ');
    }
    return 0;
}

最后

以上就是辛勤鸭子为你收集整理的2020ICPC南京 M.Monster Hunter的全部内容,希望文章能够帮你解决2020ICPC南京 M.Monster Hunter所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(41)

评论列表共有 0 条评论

立即
投稿
返回
顶部