Price Maximization

传送门

题意:
有n个商品被带到了商店,第i个商品的重量是\(a_i\), 在销售商品之前,他们必须包装包裹,在包装的时候,下面的操作会完成:

  • \(\frac{n}{2}\)个包裹,每个包裹包含确切的2个商品
  • 这个包裹的重量是\(a_i + a_j\)

一个x重包裹的价值是\(\lfloor\frac{x}{k}\rfloor\), k是题目给定的一个固定的数,将这些商品放进包裹,让最后的价值能够最大


思路:
首先,先把固定价值给求出来,固定价值都是不变的,剩下的都是余数,把余数从小到大排序,每两个余数相加不可能超过2,所以最大的贡献是1,如果一个包裹和另一个包裹能构成1,那超出的范围肯定是最小的,考虑最有可能和其他包裹构成1的,那肯定是最大的那个包裹,考虑要超出最小,所以,那肯定是从小的开始,最小的那个和当前最大的组合,第二大的可定不可能和之前的的那个小的组合前的数组合因为肯定无贡献,如果那样组合,只可能找后面的

总结:
贪心思路又多了一种,可以用想超出的贡献来进行贪心,还有任意两个余数相加,肯定不会超过一个那个取余数的两倍


点击查看代码
#include <bits/stdc++.h>
#define endl '\n'
#define IOS ios::sync_with_stdio(false);
using namespace std;

typedef long long ll;
const ll MAXN = 2e5 + 10;
ll T, n, k;
ll a[MAXN];

bool comp(ll x, ll y)
{
    return x < y;
}

int main()
{
	//IOS; cin.tie(0), cout.tie(0);
    cin >> T;
    while (T--)
    {
        cin >> n >> k;
        ll ans = 0;
        for (int i = 1; i <= n; ++i)
        {
            cin >> a[i];
            ans += a[i] / k;    //这些是固定的贡献,肯定会有的
            a[i] = a[i] % k;    
        }

        sort(a + 1, a + 1 + n, comp);

        //剩下的就是贪心的找,最后一个数 + 其中的一个数不可能有2的贡献,最多也就1的贡献,所以在满足1的贡献的情况下我要让他超出的最少,就是最贪的
        ll l = 1, r = n;
        while (l < r)
        {
            if (a[l] + a[r] >= k)
            {
                r--;
                l++;
                ans++;
            }
            else
            {
                l++;
            }
        }
        cout << ans << endl;
        
    }
	return 0;
}
/*
1
6 9
9 5 2 1 3 5
*/
posted @ 2022-08-05 15:12  YUGUOTIANQING  阅读(34)  评论(0)    收藏  举报