组装玩具(贪心)

题目描述

小华打算用n种(编号为1到n)材料组装玩具。其中第i种材料的数量为Xi个。组装一个玩具需要第i种材料Yi个。小华另外有m个万能材料,每个万能材料可以作为n种材料中的任意一个材料使用。
请编程计算小华最多可以组装多少个玩具?

输入

输入共 3 行。
第1行两个整数n和m,分别表示小华有n种材料和m个万能材料。
第2行n个正整数,其中第i个整数Xi表示小华第 i 种材料有Xi个。
第3行n个正整数,其中第i个整数Yi表示小华组装一个玩具需要第i种材料Yi个。

输出

输出共1行。
一个整数,表示小华最多可以组装多少个玩具。

样例

输入 1
1 1
1
1
输出 1
2

输入 2
3 1
1 1 1
10 10 10
输出 2
0

输入 3
3 1
13 7 20
3 2 5
输出 3
4

输入 4
2 2
3 3
2 2
输出4
2

提示

【样例1解释】
输入中小华只有1个编号为1的材料,另外还有1个万能材料。组装一个玩具需要编号为1的材料1个。所以可以用1个编号为1的材料和1个万能材料分别组装1个玩具,共可以组装2个玩具。
【样例2解释】
输入中小华第1种材料有1个,第2种材料有1个,第3种材料有1个,另外还有1个万能材料。组装一个玩具需要第1种材料10个,需要第2种材料10个,需要第3种材料10个。所有小华目前的材料只能组装0个玩具。
【样例3解释】
输入中小华第1种材料有13个,第2种材料有7个,第3种材料有20个,另外还有1个万能材料。组装一个玩具需要第1种材料3个,需要第2种材料2个,需要第3种材料5个。小华将万能材料作为1个第2种材料,可以组装4个玩具。
【样例4解释】
输入中小华第1种材料有3个,第2种材料也有3个,另外还有2个万能材料。组装一个玩具需要第1种材料2个,需要第2种材料2个。小华将1个万能材料作为1个第1种材料,将另外1个万能材料作为1个第2种材料,则可以组装2个玩具。
【数据范围约定】
50%的测试点输入数据保证 1 ≤n≤1000, 1 ≤m≤104,1≤Xi, Yi≤104
100%的测试点输入数据保证 1 ≤n≤100000, 1 ≤m≤109,1≤Xi, Yi≤109

评说

虽然知道这道题很水啊,但是莫名其妙卡了我一段时间。瞄了一眼感觉就像是俄罗斯方块那种游戏的玩法,一些节点高一些节点低,在某一列加上几个物体,然后就能消掉几行,大概就是这样。虽然我觉得用注水比较形象一点,自然而然就往低的方向流。然后马上想到贪心的方法,先读到结构体里,然后sort一下,优先级是节点高度(xi / yi),然后每次都往最低的节点加材料就行,但是看他材料的数据最多有109,这个真的迷,后来设计了一个贪心 + 前缀和的写法,复杂度低,结果WA90,调试半天心态爆炸,直接敲了一个暴力模拟发现就过了,晕倒。

分析

分析图
读入到结构体排序之后应该是这样的,然后要让所有的都弄平,多出来的东西康康能不能全部用万能材料做出玩具。

模拟如下
  1. 向全部最低级别放材料到能够做成玩具为止。
  2. 把最低级别的放完之后,再次向最低级别放材料(这意味着a1要放很多次)
  3. 结束条件,全部级别是一样,也就是正好可以做成整数的玩具,或者万能材料不够。
  4. 答案:全部放完之后,如果剩下的万能材料能够做成玩具就给他加上。如果是万能材料不够导致不能放完,那么就是节点高度最低的。
参考代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 100010;
ll sum;
struct node {
	ll x;
	ll y;
	ll z;
} a[N];
int cmp(node a, node b) {
	return (a.z < b.z);
}
int main() {
	ll n, m;
	cin >> n >> m;
	for (int i = 1; i <= n; i++) {
		cin >> a[i].x;
	}
	for (int i = 1; i <= n; i++) {
		cin >> a[i].y;
		a[i].z = a[i].x / a[i].y;
		sum += a[i].y;
	}
	sort(a + 1, a + n + 1, cmp);
	int ok = 1;
	while (m > 0 && ok) {
		int mod = 0;
		for (int i = 1; i <= n; i++) {
			if (i > 1 && a[i].z != a[i - 1].z - 1) break;
			mod += a[i].x % a[i].y;
			ll need = a[i].y - (a[i].x % a[i].y);
			if (m >= need) {
				a[i].x += need;
				a[i].z++;
				m -= need;
			}
			else {
				ok = 0;
				break;
			}
		}
		if (mod == 0 && a[1].z == a[n].z) ok = 0;
	}
	ll ans = a[1].z;
	if (a[1].z == a[n].z) {
		ans += m / sum;
	}
	else {
		for (int i = 1; i <= n; i++) {
			ans = min(ans, a[i].z);
		}
	}
	cout << ans << endl;
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值