5 倍经验日

题目背景

现在乐斗有活动了!每打一个人可以获得 5 倍经验!absi2011 却无奈的看着那一些比他等级高的好友,想着能否把他们干掉。干掉能拿不少经验的。

题目描述

现在 absi2011 拿出了 $x$ 个迷你装药物(嗑药打人可耻…),准备开始与那些人打了。

由于迷你装药物每个只能用一次,所以 absi2011 要谨慎的使用这些药。悲剧的是,用药量没达到最少打败该人所需的属性药药量,则打这个人必输。例如他用 $2$ 个药去打别人,别人却表明 $3$ 个药才能打过,那么相当于你输了并且这两个属性药浪费了。

现在有 $n$ 个好友,给定失败时可获得的经验、胜利时可获得的经验,打败他至少需要的药量。

要求求出最大经验 $s$,输出 $5s$。

输入格式

第一行两个数,$n$ 和 $x$。

后面 $n$ 行每行三个数,分别表示失败时获得的经验 $\mathit{lose}_i$,胜利时获得的经验 $\mathit{win}_i$ 和打过要至少使用的药数量 $\mathit{use}_i$。

输出格式

一个整数,最多获得的经验的五倍。

样例 #1

样例输入 #1

1
2
3
4
5
6
7
6 8
21 52 1
21 70 5
21 48 2
14 38 3
14 36 1
14 36 2

样例输出 #1

1
1060

提示

【Hint】

五倍经验活动的时候,absi2011 总是吃体力药水而不是这种属性药。

【数据范围】

  • 对于 $10\%$ 的数据,保证 $x=0$。
  • 对于 $30\%$ 的数据,保证 $0\le n\le 10$,$0\le x\le 20$。
  • 对于 $60\%$ 的数据,保证 $0\le n,x\le 100$, $10<lose_i,win_i\le 100$,$0\le use_i\le 5$。
  • 对于 $100\%$ 的数据,保证 $0\le n,x\le 10^3$,$0<lose_i\le win_i\le 10^6$,$0\le use_i\le 10^3$。

【题目来源】

fight.pet.qq.com

absi2011 授权题目

题解

题目解析

怪怪的背包题,看了题解才发现这道题可以转化为平凡的背包题.

当我们把所有的失败的经验都加起来的时候,我们背包的价值就可以转化为 胜利的exp-失败的exp 了.这样我们找到了差的最大值,那我们加上一个常数那还是最大值,最后得到的就是我们最后得到exp的最大值.

在这里我突然想起一个问题,我一直以为背包是一遍一遍扫描然后得出最大值.实际上背包的做法是暗含了所有可能的情况了,也就是 (选这个物品/不选这个物品)的最大值 可以理解为压缩版的搜索.

AC代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <iostream>
#include <cstring>
#include <cmath>
#include <string>
#include <stack>
#include <queue>
#include <vector>
#include <algorithm>
using namespace std;

#define endl "\n"
#define CIN_ ios::sync_with_stdio(0)
#define CIN cin.tie(0)
#define MAXN(size) const long long MAXN = size + 100
#define mem(name,value) memset(name,value,sizeof(name))
#define fa(a,n,p) for(int i=a;i<=n;i+=p)
#define fb(a,n,p) for(int i=a;i>=n;i-=p)
#define cin(length,var) for(int i=1;i<=length;i++) cin >> var[i]
#define T_ int T;cin >> T;while(T--)
typedef long long ll;
typedef unsigned long long ull;

MAXN(1e3);
int p[MAXN];
ll delta[MAXN],dp[MAXN];

signed main(){
int n,x;
ll sum = 0;
cin >> n >> x;
fa(1,n,1){
int lose,win;
cin >> lose >> win >> p[i];
delta[i] = win - lose;
sum += lose;
}
fa(1,n,1){
for(int j=x;j>=p[i];j--){
dp[j] = max(dp[j],dp[j-p[i]]+delta[i]);
}
}
cout << 5 * (dp[x] + sum) << endl;
return 0;
}