链接:https://ac.nowcoder.com/acm/contest/10507/B
来源:牛客网
小\text{D}D是一个喜欢研究算法的大魔法师。有一天,他在魔法森林里找到了\mathop nn棵魔法树,其中第\mathop ii棵魔法树可以生产无限块抗力为a_ia
i
,魔力为b_ib
i
的魔法石。同时,由于小\text{D}D法力强大,他有\mathop kk次机会,每次可以交换其中两棵魔法树能够产生的魔法石的魔力。
小\text{D}D可以吸收魔法石的能量。每吸收一块魔法石的能量,他的抗力就会减少对应魔法石的抗力,魔力就会增加对应魔法石的魔力。他的初始抗力为\mathop mm,魔力为\text 00。一旦他的抗力小于\text 00,他就没法施展魔法了。现在,小\text{D}D想知道,自己在抗力不小于\text 00的前提下,最大的魔力是多少。
注意,小\text{D}D必须先使用完所有的交换机会,再吸收魔法石的能量。
输入描述:
输入共\text 33行。
第一行包含\text 22个正整数n,m(1\le n,m\le 10^3)n,m(1≤n,m≤10
3
)和\text 11个非负整数k(0\le k \le 100)k(0≤k≤100)。
第二行包含\mathop nn个正整数,第\mathop ii个数表示a_i(1\le a_i \le 10^3)a
i
(1≤a
i
≤10
3
)。
第三行包含\mathop nn个正整数,第\mathop ii个数表示b_i(1\le b_i\le 10^9)b
i
(1≤b
i
≤10
9
)。
输出描述:
输出共一行,包含一个非负整数,表示最大的魔力。
示例1
输入
复制
2 5 0
1 2
1 3
输出
复制
7
说明
由于\mathop k=0k=0,所以没有交换机会。
吸收魔法树\text 11的\text 11块魔法石,吸收魔法树\text 22的\text 22块魔法石。
此时小\text{D}D的抗力=\text 5-1-2\times2=0=5−1−2×2=0,魔力=1+2\times 3=7=1+2×3=7。
示例2
输入
复制
2 5 1
1 2
1 3
输出
复制
15
说明
使用唯一的交换机会,交换魔法树\text 11,魔法树\text 22能够产生的魔法石的魔力。
吸收魔法树\text 11的\text 55块魔法石,吸收魔法树\text 22的\text 00块魔法石。
此时小\text{D}D的抗力=\text 5-1\times 5=0=5−1×5=0,魔力=3\times 5=15=3×5=15。
我们发现题目的关键是魔法树可以生产无限魔法石,所以如果我们想让魔力最多的话,我们可以选中一个抗力最小但是魔力最大的一直吸,由于我们必须把交换次数全部用光,但是我们观察数据范围,考虑特殊情况,我们发现有可能不能通过交换使得抗力最小的和魔力最大的到一块,当n为2的时候,每次只能左右交换,,当K为0的时候,我们就发现不能通过交换使得最小抗力和最大的魔力放到一块,所以我们此时需要观察,发现这不是个完全背包问题吗,求出在当前抗力下可以有的最大魔力
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <queue>
#include <map>
#include <stack>
using namespace std;
#define pair(a, b) make_pair(a, b)
#define memset(a, b) memset(a, b, sizeof a)
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
#define x first
#define y second
typedef __int128 INT;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
const int N = 1e3 + 10;
const int M = 2e5 + 10;
const int Mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int P = 13331;
int n, m, k;
int a[N], b[N];
LL f[N];
int main()
{
//freopen("C:\\Users\\86187\\Desktop\\stdin.txt", "r", stdin);
cin >> n >> m >> k;
int maxed = 0, mined = 1e3;
for (int i = 1; i <= n; i ++)
{
cin >> a[i];
mined = min(mined, a[i]);
}
for (int i = 1; i <= n; i ++)
{
cin >> b[i];
maxed = max(maxed, b[i]);
}
if (n == 1 || (k && n > 2)) cout << (LL)m / mined * maxed;
else
{
if (k & 1) swap(b[1], b[2]);
for (int i = 1; i <= n; i ++)
for (int j = a[i]; j <= m; j ++)
f[j] = max(f[j], f[j - a[i]] + b[i]);
cout << f[m] << endl;
}
return 0;
}