小D和他的魔法石

链接: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;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值