【C++算法练习题】贪心算法例题

问题一:奶酪工厂

奶牛们收购了一个奶酪工厂,接下来的 个星期里,牛奶价格和劳力价格不断起伏。第 i 周,生产一个单位奶酪需要 C_i\ (1\le C_i\le 5000) 便士。

工厂有一个货栈,保存一单位奶酪,每周需要 S\ (1\le S\le100)  便士,这个费用不会变化。货栈十分强大,可以存无限量的奶酪,而且保证它们不变质。

工厂接到订单,在第 i 周需要交付 Y_i\ (0\le Yi\le 10^4) 单位的奶酪给委托人。第 i 周刚生产的奶酪,以及之前的存货,都可以作为产品交付。请帮牛们计算这段时间里完成任务的最小代价.

输入格式

第一行两个整数 N 和 S,接下来 N 行,每行两个整数 Ci​ 和 Yi​。

输出格式

一个整数,表示最少的成本,答案可能会超过 32 位整数范围。

样例解释

  • 第 1 周生产 200 单位奶酪并全部交付;
  • 第 2 周生产 700 单位,交付 400 单位,剩下 300 单位;
  • 第 3 周交付 300 单位存货;
  • 第 4 周生产并交付 500 单位。

样例输入

4 5
88 200
89 400
97 300
91 500

样例输出

126900

问题分析

题目需要总成本最小,通过贪心的思路,即是每一周交付的成本最小即可。要么就在当前这一周进行生产,成本为 C,要么就是之前累计下来的最低值 now (也就是前几周生产成本 C 加上保存的成本 S ),取这两个的最小值,就是贪心策略。

代码

#include
using namespace std;
int main(){
    int n, s;
    //n个星期,每周需要s个便士保存
    cin >> n >> s;
    long long ans = 0;
    int now = 1e9;
    for(int i = 1; i <= n; i++){
        //生产一个单位需要c便士
        //需要交付y个单位
        int c, y;
        cin >> c >> y;
        now = min(now + s, c);	//比较成本
        ans += (long long) y * now;
    }
    cout << ans << endl;
    return 0;
}

问题二:节约用电

学校里有一条超长的走廊,可以看成是一条直线。走廊里一共有 n 盏电灯,每盏电灯的位置为 ai ​。为了响应国家的号召节约用电,校长决定关掉几盏电灯,仅维持走廊的基本光照。具体规则是,如果某盏灯的左右两盏亮着的灯距离不超过 m,就可以把这盏灯关闭。其中头尾两盏灯不允许关闭。

现在请你计算最多能关掉多少盏灯。

输入格式

第一行两个整数 n,m\ (2\le n\le 10^5,1\le m \le 10^6) ,分别表示电灯的盏数和最大距离 m。

第二行 n 个整数,表示每盏灯的位置 a_i\ (1\le a_i \le 10^6)

输出格式

一个整数,表示最多关掉电灯的数量。

样例输入

4 5
3 6 10 1

样例输出

1

问题分析

本题难度不大,需要对灯进行排序,然后遍历对比两盏灯的距离即可。

代码

#include
using namespace std;
int a[100005];
int main(){
    int n, m;
    cin >> n >> m;
    for(int i = 0; i < n; ++i){
        cin >> a[i];
    }
    //先进行排序
    sort(a, a + n);
    int ans = 0;
    int last = a[0];
    for(int i = 1; i < n - 1; ++i){
        if(a[i + 1] - last <= m){
            //说明可以关掉
            ans++;
        }else{
            last = a[i];
        }
    }
    cout << ans;
    return 0;
}

问题三:蘑菇森林

小A来到蘑菇森林,这里有 n 只僵尸蘑菇,每只僵尸蘑菇的闪避值为 x,血量为 yi。只有小A的命中值大于等于怪物的闪避值,才能对怪物造成伤害。小A一共有 m 点能量值,他每次攻击会消耗一点能量,然后造成一点伤害(单体攻击,某个怪物血量减少 1)。

现在已知小A的基础命中值为 h,身上装备增加的命中值为 b。现在小A他想知道一共能杀死多少个僵尸蘑菇。

输入格式

第一行四个整数 n,m,h,b,分别表示僵尸蘑菇的数量,能量值,基础命中值,装备的命中值加成。

接下来 n 行,每行两个整数 xi, yi​,表示每个僵尸蘑菇的闪避值和血量。

输出格式

一个整数,表示能杀死的僵尸蘑菇数量。

数据范围

1\le n \le 5000,1 \le m \le 1000,1 \le h, b \le 200,1 \le x_i \le 300,1\le y_i \le 50

样例输入

5 10 50 50
120 1
110 2
100 4
80  7
90  6

样例输出

2

问题分析

首先,我们需要判断蘑菇怪的闪避值是否大于我们的命中值;否则即便遇上了也没有任何意义。第二点,我们需要判断我们的能量与蘑菇怪的血量,为了能打死更多的蘑菇怪,我们的策略是先把血量小的蘑菇怪打掉,然后逐一向血量大的对比,直到打不过为止。

代码

#include
using namespace std;
int mogu[5005];
int main(){
    int n, m, h, b;
    cin >> n >> m >> h >> b;
    h += b;
    int count = 0;
    for(int i = 0; i < n; ++i){
        int x, y;
        cin >> x >> y;
        if(h >= x){
            mogu[count++] = y;
        }
    }
    sort(mogu, mogu + count);
    int ans = 0;
    for(int i = 0; i < count; i++){
        if(m >= mogu[i]){
            m -= mogu[i];
            ans++;
        }
    }
    cout << ans;
    return 0;
}

总结

  • 读懂题。题目相对来说比较复杂,读题很重要!
  • 每步都要保证是最优的。

你可能感兴趣的:(数据结构与算法)