存储容器的优化 | 豆包MarsCode AI刷题

80 阅读3分钟

问题描述

小C管理着一个会员数据库,她希望能够尽可能高效地存储会员信息。每个会员的存储成本可以表示为一个线段长度  ai  \;a_i\;,而她拥有的存储空间由  m  \;m\;块容器  bi  \;b_i\;组成。每个会员和每块容器的长度可以是  1  \;1\;  2  \;2\;

为了提高存储效率,如果会员的信息存储在容器的两端位置,其存储成本可以压缩为一半,即  ai  /  2  \;{a_i}\;/\;{2}\;。但是,一个会员只能被压缩一次。目标是最大化能够存储的会员数量,并计算存储成本的总和。


测试样例

样例1:

输入:n = 5 , m = 2 , a = [1, 2, 2, 1, 2] , b = [2, 1]
输出:4

样例2:

输入:n = 4 , m = 3 , a = [2, 1, 1, 2] , b = [1, 2, 1]
输出:4

样例3:

输入:n = 6 , m = 2 , a = [2, 1, 1, 2, 1, 2] , b = [2, 2]
输出:5

注记

这道题没有表达清楚solution返回的数值的含义。实际上,solution返回的数值表示最多能够存储多少位会员的信息。

分析

问题的目标是 最大化 存储的会员数量 。每个会员的长度可以是  1  \;1\;  2  \;2\;; 而任何会员可用的容器都是相同的,亦即总的存储容量与会员类型无关。因为总的存储容量是确定的, 所以存储的每个会员的长度越小,存储的会员数量就越多。因此,无论如何,我们应当优先存储长度为  1  \;1\;的会员;在长度为  1  \;1\;的会员都已经被存储、并且还有剩余容器的情况下,才考虑存储长度为  2  \;2\;的会员。

如何存储长度为1的会员

  1. 长度为  1  \;1\;容器,在容器两端使用压缩技术,得1=12+121=\frac{1}{2}+\frac{1}{2},即
    • 能存储2位存储长度为1的会员。
    • 1单位存储空间存储了2位用户。
  2. 长度为  2  \;2\;容器,在容器两端使用压缩技术,得2=12+1+122=\frac{1}{2}+1+\frac{1}{2},即
    • 能存储3位存储长度为1的会员。
    • 2单位存储空间存储了3位用户,亦即平均1单位存储空间存储了1.5位用户。

注意到,虽然相比单个长度为  1  \;1\;容器,单个长度为  2  \;2\;容器能够存储更多用户, 但是就单位空间能够存储的用户数目而言,有2>1.52>1.5, 亦即长度为  1  \;1\;容器能够存储更多用户,是更好的选择。 (另一种理解方式:给定总存储空间为2,两个长度为  1  \;1\;容器能够存储4位用户,而 一个长度为  2  \;2\;容器只能存储3位用户。)

另外,在存储完长度为  1  \;1\;的会员时,如果容器有剩余空间,那么应该考虑将其用于 存储长度为  2  \;2\;的会员。因为2/212/2\not<12/2<2122/2<2-\frac{1}{2}2/2212122/2\not<2-\frac{1}{2}-\frac{1}{2}2/221212/2\not<2-\frac{1}{2}-1

如何存储长度为2的会员

可以类比上文的思路。

题解

#include <algorithm>
#include <vector>
using namespace std;

int solution(const int n, const int m, const vector<int>& a, const vector<int>& b)
{
    int n_a1 = count(a.begin(), a.end(), 1), n_a2 = n - n_a1;
    int n_b1 = count(b.begin(), b.end(), 1), n_b2 = m - n_b1;
    int ans = 0, n_stores;
    while (n_a1)
        if (n_b1) {
            n_stores = min(2, n_a1);
            n_a1 -= n_stores;
            ans += n_stores;
            --n_b1;
        } else if (n_b2) {
            n_stores = min(3, n_a1);
            if (n_stores == 1 && n_a2) {
                --n_a2;
                ++ans;
            }
            n_a1 -= n_stores;
            ans += n_stores;
            --n_b2;
        } else
            break;
    while (n_a2)
        if (n_b1) {
            --n_b1;
            --n_a2;
            ++ans;
        } else if (n_b2) {
            n_stores = min(2, n_a2);
            n_a2 -= n_stores;
            ans += n_stores;
            --n_b2;
        } else
            break;
    return ans;
}