C++知识点总结(17):贪心算法

一、文件操作

1. 加头文件

#include <cstdio>

cstdio 表示 C 语言中标准的输入输出。

2. 加函数

int main()
{
    freopen("输入文件名.in", "r", stdin);
    freopen("输出文件名.out", "w", stdout);
    // 这里写代码...
    fclose(stdin);
    fclose(stdout);
    return 0;
}

3. 写输入

在与程序同一目录下创建 name.in 文件,在里面输入要输入的内容,然后运行程序,得到 name.out 文件,就可以看到输出的内容了。

二、贪心算法

1. 概念

贪心算法 greedy algorithm
在对问题求解时,总是做出在当前看来是最好的选择,来期望达到整体最优。

2. 洛谷P2240 最多的金币

2.1 审题

题目描述

阿里巴巴走进了装满宝藏的藏宝洞。藏宝洞里面有 N ( N ≤ 100 ) N(N \le 100) N(N100) 堆金币,第 i i i 堆金币的总重量和总价值分别是 m i , v i ( 1 ≤ m i , v i ≤ 100 ) m_i,v_i(1\le m_i,v_i \le 100) mi,vi(1mi,vi100) 。阿里巴巴有一个承重量为 T ( T ≤ 1000 ) T(T \le 1000) T(T1000) 的背包,但并不一定有办法将全部的金币都装进去。他想装走尽可能多价值的金币。所有金币都可以随意分割,分割完的金币重量价值比(也就是单位价格)不变。请问阿里巴巴最多可以拿走多少价值的金币?

输入格式

第一行两个整数 N , T N,T N,T
接下来 N N N 行,每行两个整数 m i , v i m_i,v_i mi,vi

输出格式

一个实数表示答案,输出两位小数。

样例1

输入

4 50
10 60 
20 100 
30 120 
15 45

输出

240.00 

2.2 解题思路

  • 求除 n n n 堆金币的单位价值,也就是这对金币的价值除以重量。
  • 把这 n n n 堆金币按照单价排序,从高到低遍历。
  • 如果背包中剩余的重量大于等于这对金币的重量,就把这对拿走。
  • 否则将这对金币分割,把剩余的空间全部装满。

2.3 参考答案

#include <iostream>
#include <iomanip>
#include <algorithm>
using namespace std;

int n, t;
double weight;

struct Node
{
    int m, v;
    double per;
}a[105];

bool cmp(Node a, Node b)
{
    return a.per > b.per;
}

int main()
{
    cin >> n >> t;
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i].m >> a[i].v;
        a[i].dj = a[i].v * 1.0 / a[i].m; // 计算单价
    }
    sort(a+1, a+n+1, cmp); // 排序
    
    // 拿金币
    for (int i = 1; i <= n; i++)
    {
        if (a[i].m <= t) // 不超载的情况下
        {
            weight += a[i].v; // 计算载重
            t -= a[i].m; // 计算剩余重量
        }
        else
        {
            weight += a[i].per * t;
            break;
        }
    }
    cout << fixed << setprecision(2) << w;
    return 0;
}

3. 洛谷P2240反向

3.1 审题

题目描述

有一批快递要装上一辆载重量为 c c c 的快递车进行运送。第 i i i 个快递的重量为 W i W_i Wi 。由于每件快递都很小,几乎不占快递车的空间,但是都比较重。为了节省成本,因此需要考虑在装载体积不受限制的情况下,将尽可能多的快递装上快递车,请你编程帮助快递小哥求出来最多能装载多少件快递。

输入描述

第一行共两个整数 N , c N,c N,c ,表示快递的件数和快递车的载重量。
第二行共有 N N N 个整数,分别表示快递的重量 W i W_i Wi

输出描述

共一行,输出 1 1 1 个整数,表示最多能装载的快递件数。

样例1

输入

8
400 100 200 50 90 150 50 20 80

输出

6

提示

对于 100 % 100% 100 的数据, N ≤ 100 N≤100 N100 c ≤ 10000 c≤10000 c10000

3.2 参考答案

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

int n, c, maxn = 0;
int a[105];

int main()
{
    cin >> n >> c;
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
    }
    sort(a+1, a+n+1);
    for (int i = 1; i <= n; i++)
    {
        if (a[i] <= c)
        {
            c -= a[i];
            maxn++;
        }
        else
        {
            break;
        }
    }
    cout << maxn;
	return 0;
}

4. 贪心的资本家

4.1 审题

题目描述

可多饭店本月新收到若干个不同的菜单,制作这些菜单上的菜的难易程度为一级、二级、三级…同样,能够制作不同难度菜单的厨师也被分为若干星级,并且 x x x 星级的厨师能够完成 x x x 级别及以下的所有菜单上的菜,高星级的菜优先由高星级的厨师完成。现有 m m m 个菜单需要制作, n n n 个空闲厨师,请问能否完成所有菜单呢?如果可以,最少的花费是多少呢?注:每个厨师当月只能完成一份菜单,厨师的工资就是厨师的星级。

输入描述

输入文件为 capital.in
输入第一行两个整数 m 和 n,分别表示需要制作的菜单量和空闲厨师的人数。
第二行 m 个整数,表示每个菜单的难易级别;
第三行 n 个整数,表示每个厨师的星级。

输出描述

输出文件为 capital.out
如果可以完成:第一行输出最小花费,接下来m行每行两个整数,分别表示菜单级别与相应的厨师级别(用空格隔开)。
否则,直接输出“Failed”

样例1

输入

5 2 
5 4 1 2 3 
7 8

输出

Failed

样例2

输入

5 7 
5 4 6 6 3 
3 5 9 10 6 8 5 

输出

27 
3 3 
4 5 
5 5 
6 6 
6 8

提示

1 ≤ n , m ≤ 20000 1\le n,m \le20000 1n,m20000

4.2 参考答案

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;

int n, m, j, money;
int food[20005];
int cook[20005];

struct Node
{
    int f, c;
}f[20005];

int main()
{
    freopen("capital.in", "r", stdin);
    freopen("capital.out", "w", stdout);
    
    cin >> m >> n;
    if (n < m)
    {
        cout << "Failed";
        fclose(stdin);
        fclose(stdout);
        return 0;
    }
    
    for (int i = 1; i <= m; i++)
    {
        cin >> food[i];
    }
    for (int i = 1; i <= n; i++)
    {
        cin >> cook[i];
    }
    
    sort(food+1, food+m+1);
    sort(cook+1, cook+n+1);
    
    j = 1;
    for (int i = 1; i <= m; i++)
    {
        while (food[i] > cook[j])
        {
            j++;
        }
        if (j > n)
        {
            cout << "Failed";
            fclose(stdin);
            fclose(stdout);
            return 0;
        }
        money += cook[j];
        f[i].f = food[i];
        f[i].c = cook[j];
        j++;
    }
    
    cout << money << endl;
    for (int i = 1; i <= m; i++)
    {
        cout << f[i].f << " " << f[i].c << endl;
    }
    
    fclose(stdin);
    fclose(stdout);
    return 0;
}
  • 17
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用C++实现会议安排问题的贪心算法示例代码: ```cpp #include <iostream> #include <vector> #include <algorithm> // 定义会议结构体 struct Meeting { int start; int end; }; // 比较函数,按照会议结束时间升序排序 bool compare(Meeting m1, Meeting m2) { return m1.end < m2.end; } // 贪心算法实现会议安排 std::vector<Meeting> scheduleMeetings(std::vector<Meeting>& meetings) { // 按照结束时间排序会议 std::sort(meetings.begin(), meetings.end(), compare); std::vector<Meeting> schedule; // 会议安排列表 schedule.push_back(meetings[0]); // 将第一个会议加入安排列表 for (int i = 1; i < meetings.size(); i++) { // 如果当前会议与已安排的最后一个会议不冲突,则将该会议加入安排列表 if (meetings[i].start >= schedule.back().end) { schedule.push_back(meetings[i]); } } return schedule; } int main() { std::vector<Meeting> meetings = {{1, 3}, {2, 4}, {3, 6}, {5, 7}, {8, 9}, {9, 10}}; std::vector<Meeting> schedule = scheduleMeetings(meetings); // 输出会议安排 for (int i = 0; i < schedule.size(); i++) { std::cout << "Meeting " << i+1 << ": " << schedule[i].start << "-" << schedule[i].end << std::endl; } return 0; } ``` 以上代码使用了结构体 `Meeting` 来表示一个会议,其中包含开始时间和结束时间。首先,通过定义一个比较函数 `compare` 来按照会议结束时间进行排序。然后,通过 `scheduleMeetings` 函数来实现会议安排的贪心算法。最后,在 `main` 函数中调用 `scheduleMeetings` 函数并输出会议安排结果。 运行以上代码,会输出以下结果: ``` Meeting 1: 1-3 Meeting 2: 5-7 Meeting 3: 8-9 ``` 这表示在给定的会议列表中,按照贪心算法安排的会议有三个:第一个会议从1到3,第二个会议从5到7,第三个会议从8到9。这些会议之间不存在时间冲突,并且结束时间最早。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值