ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

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

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

贪心算法

  • 一、文件操作
    • 1. 加头文件
    • 2. 加函数
    • 3. 写输入
  • 二、贪心算法
    • 1. 概念
    • 2. 洛谷P2240 最多的金币
      • 2.1 审题
      • 2.2 解题思路
      • 2.3 参考答案
    • 3. 洛谷P2240反向
      • 3.1 审题
      • 3.2 参考答案
    • 4. 贪心的资本家
      • 4.1 审题
      • 4.2 参考答案

一、文件操作

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;
}
返回列表