贪心 D-砝码

砝码

题目链接:砝码
在这里插入图片描述

题解

思路

题目要求尽可能多的带走砝码,那么我们就要从重量最小的开始带。
由题意,任意两个砝码之间都有倍数关系,则可以从砝码中找到最小的重量,我们暂时称之为砝码的重量单位。
其余砝码的重量都可以表示为若干个砝码的重量单位。

对于容器,要带走一个砝码,必须保证其剩余容量大于等于该砝码。根据上文所得,我们可以将容器容量也表示为若干个砝码的重量单位,多余部分将不能带走任何砝码,故可以忽略不计。

联想二进制等进制, 我们将砝码的种类表示成X进制,并将容器容量用X进制表示。

实现

kind数组:用于存储砝码的种类,以便将容量表示成X进制的数字。
digit数组digit[i]=容器所能容纳的该种砝码的数量。利用上文提到的“砝码的重量单位”,每一个大容器都可以拆分成若干个小容器,即加减法中的借位操作。

在实际计算中,我们遍历经过升序排序后的所有的砝码。对于砝码w[i],去寻找该砝码对应的种类在kind数组中的下标,以对应地寻找digit数组中的数量digit[i],当digit[i]不为0时,表明当前容量可以存储该砝码;当digit[i]等于0时,判断是否可以借位,借位后同digit[i]不为0的情况,不能借位则表明不能存储该砝码,由于砝码重量经过升序排序,故若当前砝码不能存储,则其后的所有砝码也不能存储,此时可直接结束,输出答案(不输出接着判断也行)。

AC代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdlib>
#include<string>
#include<queue>
#include<map>
#include<stack>
#include<list>
#include<set>
#include<deque>
#include<vector>
#include<ctime>

using namespace std;
//#pragma GCC optimize(2)
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define ull unsigned long long
#define ll long long
#define rep(i, x, y) for(int i=x;i<=y;i++)
#define mms(x, n) memset(x, n, sizeof(x))
#define mmc(a, b) memcpy(a, b, sizeof(b))
#define INF (0x3f3f3f3f)
#define mod (ull)(1e9+7)
typedef pair<int, int> P;

namespace FastIO {
    const int bufsiz = 1 << 22;
    char buf[bufsiz];

    inline char getch() {
        static int tot;
        tot++;
        if (tot == bufsiz) {
            fread(buf, 1, bufsiz, stdin);
            tot = 0;
        }
        return buf[tot];
    }

    inline int read() {
        int x = 0;
        char c = getch();
        while (!isdigit(c))c = getch();
        while (isdigit(c))x = x * 10 + c - '0', c = getch();
        return x;
    }
}
using FastIO::read;
const int N = 1e5 + 10;
int n, m;
int digit[N];
int cap[N], w[N];
int kind[N], top;

bool check(int pos) {
    for (int i = pos + 1; i <= top; i++) {
        if (digit[i]) {
            digit[i]--;
            digit[pos] += kind[i] / kind[pos];
            return true;
        }
    }
    return false;
}

int main() {
//    freopen("input.txt", "r", stdin);
//    freopen("output.txt", "w", stdout);
    n = read(), m = read();
    rep(i, 1, n) cap[i] = read();
    rep(i, 1, m)w[i] = read();
    sort(w + 1, w + m + 1);
    rep(i, 1, m) if (w[i] != w[i - 1]) kind[++top] = w[i];
    rep(i, 1, n) {
        for (int j = top; j >= 1; j--) {
            digit[j] += cap[i] / kind[j];
            cap[i] %= kind[j];
        }
    }
    int ans = 0;
    rep(i, 1, m) {
        rep(j, 1, top) {
            if (w[i] == kind[j]) {
                if (digit[j]) {
                    digit[j]--;
                    ans++;
                } else if (check(j)) {
                    digit[j]--;
                    ans++;
                }
                break;
            }
        }
    }
    printf("%d", ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_45934120/article/details/107660703