日常训练2025-1-8
E小红的双生英雄
思路
读题后跟容易发现是一道分组背包的题,转移也比较简单。有一个做动态规划题的技巧是,如果题目相较于传统的DP题有一些其他的约束条件,则把约束条件写成DP的一个维度就行。
代码
#include <bits/stdc++.h>
typedef std::pair<long long, long long> pll;
typedef std::pair<int, int> pii;
#define INF 0x3f3f3f3f
#define MOD 998244353
using i64 = long long;
const int N = 1e5+5;
void solve(){
int n, C, m;
std::cin >> n >> C >> m;
std::vector<pll> tmp(n+1);
std::vector<bool> st(n+1);
for (int i = 1; i <= n; i++) {
int cost, v;
std::cin >> cost >> v;
tmp[i] = pll(cost, v);
}
std::vector<std::vector<pll>> a;
for (int i = 0; i < m; i++){
int u, v, w;
std::cin >> u >> v >> w;
st[u] = st[v] = true;
a.push_back({tmp[u], tmp[v], {tmp[u].first + tmp[v].first, tmp[u].second + tmp[v].second + w}});
}
for (int i = 1; i <= n; i++){
if (!st[i]) a.push_back({tmp[i]});
}
std::vector<std::vector<i64>> dp(C+1, std::vector<i64>(5));
std::vector<std::vector<i64>> ndp(C+1, std::vector<i64>(5));
for (auto s : a){
ndp = dp;
for (int i = 0; i < s.size(); i++){
auto [cost, atk] = s[i];
int ok = i == 2;
for (int j = C; j >= cost; j--){
for (int k = 4; k >= 1 + ok; k--){
dp[j][k] = std::max(dp[j][k], ndp[j-cost][k-1-ok] + atk);
}
}
}
}
i64 ans = 0;
for (int j = 0; j <= C; j++){
for (int k = 0; k <= 4; k++){
ans = std::max(ans, dp[j][k]);
}
}
std::cout << ans << '\n';
}
signed main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout<<std::setiosflags(std::ios::fixed)<<std::setprecision(2);
int t = 1, i;
for (i = 0; i < t; i++){
solve();
}
return 0;
}
标签:std,tmp,cost,训练,int,2025,vector,日常,dp
From: https://www.cnblogs.com/califeee/p/18660337