首页 > 试题广场 >

小红的双生英雄

[编程题]小红的双生英雄
  • 热度指数:2347 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
\hspace{15pt}小红有 n 个英雄,第 i 个英雄的 cost 是 a_i,战斗力为 b_i。另外,存在一些“双生英雄”关系,如果同时上阵某一对英雄,则可以获得额外的战斗力收益。
\hspace{15pt}现在小红最多可以上阵四名英雄,且要求总 cost 不超过C。小红希望你求出组队的最大战斗力。

输入描述:
\hspace{15pt}第一行输入三个整数 n,C,m \left(1 \leqq n,C \leqq 10^3;\ 0 \leqq m \leqq n/2\right) 代表英雄数量、总cost限制、双生英雄的对儿数。 
\hspace{15pt}此后 n 行,第 i 行输入两个正整数 a_i,b_i \left(1 \leqq a_i,b_i \leqq 10^9\right) 代表第 i 个英雄的 cost 和战斗力。
\hspace{15pt}此后 m 行,第 i 行输入三个正整数 u_i,v_i,w_i \left(1 \leqq u_i,v_i \leqq n; u_i \neq v_i; 1 \leqq w_i \leqq 10^9\right) 代表第 u_i 和第 v_i 个英雄是双生英雄,同时上阵可以额外增加 w_i 战斗力。

\hspace{15pt}除此之外,保证每个英雄最多只存在一对双生英雄关系。对于 40\% 的用例,额外保证 m=0


输出描述:
\hspace{15pt}输出一个整数,代表组队的最大战斗力。
示例1

输入

4 10 1
3 9
4 10
6 15
8 20
1 2 15

输出

34

说明

\hspace{15pt}在这个样例中,小红可以选择上阵第一、二个英雄,获得 9+10+15=34 的战斗力。我们可以证明,这是符合要求的最大战斗力。
示例2

输入

4 1 1
3 9
4 10
6 15
8 20
1 2 15

输出

0
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


#define MAX(x,y) ((x) > (y)) ? (x) : (y)

typedef struct actor_info {
    int cost;
    int power;
    int is_pair;
} ActorInfo;

typedef struct pair_actor {
    int x;
    int y;
    int x_power;
    int y_power;
    int x_cost;
    int y_cost;
    int pair_cost;
    uint64_t pair_power;
} PairActor;

int main() {
    int actor_cnt = 0;
    int max_cost = 0;
    int pair_cnt = 0;
    scanf("%d %d %d", &actor_cnt, &max_cost, &pair_cnt);

    ActorInfo info[actor_cnt + 1];
    memset(info, 0, sizeof(info));
    for (int i = 1; i <= actor_cnt; i++) {
        scanf("%d %d", &info[i].cost, &info[i].power);
    }

    PairActor pair[pair_cnt];
    memset(pair, 0, sizeof(pair));
    for (int i = 0; i < pair_cnt; i++) {
        scanf("%d %d %ld", &pair[i].x, &pair[i].y, &pair[i].pair_power);

        info[pair[i].x].is_pair = 1;
        info[pair[i].y].is_pair = 1;

        pair[i].x_power = info[pair[i].x].power;
        pair[i].y_power = info[pair[i].y].power;
        pair[i].x_cost = info[pair[i].x].cost;
        pair[i].y_cost = info[pair[i].y].cost;
        pair[i].pair_cost = pair[i].x_cost + pair[i].y_cost;
        pair[i].pair_power += info[pair[i].x].power + info[pair[i].y].power;
    }


    uint64_t dp[5][1001] = {0};
    for (int i = 1; i <= actor_cnt; i++) {
        // 跳过双生英雄
        if (info[i].is_pair) {
            continue;
        }
        for (int j = 4; j > 0; j--) {
            for (int k = max_cost; k >= info[i].cost; k--) {
                // 两种情况最大值
                // 不选i英雄:dp[j][k]
                // 选i英雄:dp[j - 1][k - info[i].cost] + info[i].power
                dp[j][k] = MAX(dp[j][k], dp[j - 1][k - info[i].cost] + info[i].power);
            }
        }
    }


    for (int i = 0; i < pair_cnt; i++) {
        for (int j = 4; j > 0; j--) {
            for (int k = max_cost; k > 0; k--) {
                // 4种情况最大值
                // 不选:dp[j][k]
                // 选 x y:dp[j - 2][k - pair[i].pair_cost] + pair[i].pair_power
                // 选x:dp[j - 1][k - pair[i].x_cost] + pair[i].x_power
                // 选y:dp[j - 1][k - pair[i].y_cost] + pair[i].y_power
                uint64_t best_building = dp[j][k];
                if (k > pair[i].pair_cost && j >= 2) {
                    best_building = MAX(best_building, dp[j - 2][k - pair[i].pair_cost] + pair[i].pair_power);
                }
                if (k > pair[i].x_cost) {
                    best_building = MAX(best_building, dp[j - 1][k - pair[i].x_cost] + pair[i].x_power);
                }
                if (k > pair[i].y_cost) {
                    best_building = MAX(best_building, dp[j - 1][k - pair[i].y_cost] + pair[i].y_power);
                }
                dp[j][k] = best_building;
            }
        }

    }

    uint64_t max_power = 0;
    for (int i = 1; i <= 4; i++) {
        max_power = max_power > dp[i][max_cost] ? max_power : dp[i][max_cost];
    }
    printf("%ld\n", max_power);
}

发表于 2025-10-08 16:14:07 回复(0)