题目描述
小华打算用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,调试半天心态爆炸,直接敲了一个暴力模拟发现就过了,晕倒。
分析
读入到结构体排序之后应该是这样的,然后要让所有的都弄平,多出来的东西康康能不能全部用万能材料做出玩具。
模拟如下
- 向全部最低级别放材料到能够做成玩具为止。
- 把最低级别的放完之后,再次向最低级别放材料(这意味着a1要放很多次)
- 结束条件,全部级别是一样,也就是正好可以做成整数的玩具,或者万能材料不够。
- 答案:全部放完之后,如果剩下的万能材料能够做成玩具就给他加上。如果是万能材料不够导致不能放完,那么就是节点高度最低的。
参考代码
#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;
}