贪心

1. 简介

基本原理:每一步都选择局部最优解,并且尽量不考虑对后续的影响,最终达到全局最优解

局限性:不能保证获得全局最优解,但在某些问题上具有高效性

“分类讨论”,“最小代价”,“最大价值”

贪心题型太多,要多练

2. 例题

最小化战斗力差距

#include <bits/stdc++.h>
using ll = long long;
using namespace std;

const int N = 1e5 + 10;
ll a[N], b[N];

int main()
{
    int n;
    cin >> n;
    for(int i = 1; i <= n; i ++ ) cin >> a[i];

    sort(a + 1, a + n + 1);
    ll res = 0x3fffffffffffff;
    for(int i = 2; i <= n; i ++ )
    {
        b[i] = a[i] - a[i - 1];
        res = min(res, b[i]);
    }
    cout << res << endl;

    return 0;
}

谈判

#include <bits/stdc++.h>
using ll = long long;
using namespace std;

priority_queue<ll, vector<ll>, greater<ll>> pq;

int main()
{
    int n; cin >> n;
    for(int i = 1; i <= n; i ++ )
    {
        ll x; cin >> x;
        pq.push(x);
    }
    ll ans = 0;
    while(pq.size() > 1)
    {
        ll x = pq.top(); pq.pop();
        ll y = pq.top(); pq.pop();
        
        ans += x + y;
        pq.push(x + y);
    }
    cout << ans << endl;
    return 0;
}
优先队列(priority_queue):一个有权值的“队列”

表现为一个以vector表现的完全二叉树

权值高的排在前面

priority_queue<Type, Container, Functional>

Type代表数据类型,Container代表容器类型,缺省状态为vector; Functional是比较方式
默认采用大顶堆

大堆:

priority_queue<int,vector<int>, less<int>> q;

小堆:

priority_queue<int,vector<int>, greater<int>> q;

自定义比较函数:

struct cmp
{
    bool operator()(int a, int b)
    {
        return a > b;
    }
}
priority_queue<int, vector<int>, cmp> q;

纪念品分组

思路:最大配最小,配不上的话最大单独一组

双指针实现:

#include <bits/stdc++.h>
using namespace std;

const int N = 30010;
int a[N];

int main()
{
    int w, n;
    cin >> w >> n;
    for(int i = 1; i <= n; i ++ ) cin >> a[i];
    sort(a + 1, a + n + 1);
    
    int l = 1, r = n, ans = 0;

    while(l <= r)
    {
        ans ++ ;
        if(l == r) break;

        if(a[l] + a[r] <= w)
        {
            l ++ ;
            r -- ;
        }else r -- ;
    }
    cout << ans << endl;
    return 0;
}

分糖果

思路:分类讨论

  1. 字符串全相等:尽量平均分
  2. s[x] == s[1]:前x - 1个一人一个,x ~ n一人独享
  3. s[x] != s[1]:前x个一人一个,后面x ~ n这一坨扔给第一个人
#include <bits/stdc++.h>
using namespace std;

const int N = 1e6 + 10;
char s[N];

int main()
{
    int n, x;
    cin >> n >> x;
    cin >> s + 1;
    sort(s + 1, s + n + 1);

    if(s[1] == s[n])
    {
        // 尽量平均分,加上 (n % x ? 1 : 0) 
        for(int i = 1; i <= n / x + (n % x ? 1 : 0); i ++ ) cout << s[1];
    }else if(s[1] == s[x])
    {
        for(int i = x; i <= n; i ++ ) cout << s[i];
    }else cout << s[x];

    return 0;
}

最大的卡牌价值

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

const int N = 1e5 + 9;
ll a[N], b[N];
vector<ll> c;

bool cmp(const ll &m, const ll &n)
{
    return m > n;
}

int main()
{
    ll n, k;
    cin >> n >> k;
    ll ans = 0;

    for(ll i = 1; i <= n; i ++ )
    {
        cin >> a[i];
        ans += a[i];
    } 
    for(ll i = 1; i <= n; i ++ ) cin >> b[i];

    for(ll i = 1; i <= n; i ++ )
    {
        if(b[i] > a[i])
        {
            c.push_back(b[i] - a[i]);
        }
    }
    sort(c.begin(), c.end(), cmp);
    ll t = min(k, (ll)c.size());
    for(ll i = 0; i < t; i ++ )
    {
        ans += c[i];
    }
    cout << ans << endl;
}

明日方舟大作战!

与其说是贪心,我觉得更像是背包dp

#include <bits/stdc++.h>
using namespace std;

const int N = 1e5 + 10;
int atk[N], cst[N], f[N];

int main()
{
    int n, m, B;
    cin >> n >> m >> B;
    for(int i = 1; i <= n; i ++ ) cin >> atk[i] >> cst[i];

    for(int i = 1; i <= n; i ++ )
    {
        for(int j = B; j >= cst[i]; j -- )
        {
            f[j] = max(f[j], f[j - cst[i]] + atk[i]);
        }
    }

    int max_life = 0;
    for(int i = 1; i <= m; i ++ )
    {
        int life;
        cin >> life;
        max_life = max(max_life, life);
    }

    int max_atk = f[B];
    if(max_atk == 0)
    {
        cout << -1 << endl;
        return 0;
    }
    
    int rounds = (int) ceil((double) max_life / max_atk);
    cout << rounds << endl;
    return 0;
}

值得注意的是这个向上取整的方式:int rounds = (int) ceil((double) max_life / max_atk);

首先,将 max_life 转换为双精度浮点数(double),然后计算 max_life 除以 max_atk 的结果,得到一个双精度浮点数(double)值。

接下来,使用 ceil() 函数将结果向上取整,以得到一个整数值。最后,将结果强制转换回整数类型(int),并将结果赋值给 rounds 变量。


南池北塘
1 声望0 粉丝