题目链接:https://ac.nowcoder.com/acm/contest/886/J
题意:题目中的货币当做技能点,题目中给n个技能,每个技能满级都是m级,技能升级可能是获得技能点,也可能是消耗技能点,当n个技能的最小等级技能分别为1到m级是,分别会获得d1 d2 …dn 技能点,d【i】可以是正的,也可以是负的。求最多能盈利多少技能点
题解:求出n个技能中最小等级分别是0级,1级,2级,…,m级的最大盈利,然后找出最大的那个就是答案。先求出技能全部升到0级,1级,2级,… ,m级的盈利,然后对于每种情况,每个技能求出继续往后升级的最大盈利,是正的就加上,但不能全加,全加最小技能等级就不是当前这种情况了,更新完后的就是最小等级分别是0级,1级,2级,…,m级的最大盈利。怎么求继续往后升级的最大盈利,用dp,假如只有一行,技能升级所需的技能点为v数组,dp[m]=0,因为不能继续往后升了,然后从后往前,dp[i]=max( v[i+1],v[i+1] + dp[i+1] )。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn = 1005;
struct node {
ll value[maxn];
ll dp[maxn];
}p[maxn];
ll he[maxn];
ll ans;
ll de[maxn];
int n, m;
int main()
{
int lun=0;
int t;
cin >> t;
while (t--) {
lun++;
scanf("%d%d", &n, &m);
memset(he, 0, sizeof(he));
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
scanf("%lld", &p[i].value[j]);
p[i].value[j] *= -1;
he[j] += p[i].value[j];
}
p[i].dp[m] = 0;
for (int j = m - 1; j >= 0; j--) {
p[i].dp[j] = max(p[i].value[j + 1], p[i].value[j + 1] + p[i].dp[j + 1]);
}
}
for (int i = 1; i <= m; i++) {
scanf("%lld", &de[i]);
he[i] += de[i];
he[i] += he[i - 1];
}
ans = 0;
for (int i = 0; i < m; i++) {
bool full = true;
for (int j = 1; j <= n; j++) {
if (p[j].dp[i] > 0) {
he[i] += p[j].dp[i];
}
if (p[j].dp[i] < 0)
full = false;
}
if (full == true) {
ll min0 = p[1].dp[i];
for (int j = 2; j <= n; j++) {
min0 = min(p[j].dp[i], min0);
}
he[i] -= min0;
}
}
for (int i = 0; i <= m; i++) {
ans = max(ans, he[i]);
}
printf("Case #%d: %lld\n",lun, ans);
}
}
本文解析了一个算法问题,目标是在给定的技能升级规则下,通过动态规划策略计算能够获得的最大技能点数。文章详细介绍了如何使用DP算法来解决这一问题,包括初始化、状态转移等关键步骤。
J-Upgrading Technology&spm=1001.2101.3001.5002&articleId=98597473&d=1&t=3&u=b97f2f860e9f4437a8d348f907f1b561)
219

被折叠的 条评论
为什么被折叠?



