算法学习21:贪心02(一些贪心的题目)
文章目录
前言:
提示:以下是本篇文章正文内容:
一、贪心的题目(猜 + 验证)(这里的题目比较简单,但贪心算法本身是比较复杂的)
1. 排队打水:
/*
有n个人排队到一个水龙头处打水,第i个人装满水所需要的时间是ti,请问如何安排它们的打水顺序才能使所有人的等待时间之和最小。
输入:
第一行包含整数n
第二行包含n个整数,其中第i个整数表示第i个人装满水所花费的时间ti
输出:
输出一个整数,表示最小的等待时间之和
数据范围:1<= n <= 10^5 1<= ti <= 10^4
*/
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N = 100010;
int n;
int t[N];
int main()
{
scanf("%d", &n);
for(int i = 0; i < n; i ++) scanf("%d", &t[i]);
sort(t, t + n);
LL res = 0;
for(int i = 0; i < n; i ++) res += t[i] * (n - i - 1);// 遍历
printf("%lld", res);
return 0;
}
2. 货仓选址:
/*
在一条数轴上有n加商店,它们的坐标分别为A1 ~ An
现在需要再数轴上建立一家货仓,每天清晨,从货仓到每家商店都要运送一车商品。
为了提高效率,求把货仓建在何处,可以使得货仓到每家商店的距离之后最小。
输入:
第一行输入整数n
第二行n个整数A1 ~ An
输出:距离之和的最小值
数据范围:1<= N <= 10^5
*/
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 100010;
int n;
int a[N];
int main()
{
scanf("%d", &n);
for(int i = 0; i < n; i ++) scanf("%d", &a[i]);
sort(a, a + n);
int res = 0;
for(int i = 0; i < n; i ++) res += abs(a[i] - a[n / 2]);// 中位数
printf("%d\n", res);
return 0;
}
3. 耍杂技的牛:(数学推理???😰薄弱环节)
/*
有n头牛(编号为1~n),进行叠罗汉表演,表演时,每头牛站在彼此的身上,形成一个高高的“垂直堆叠”
每头牛都要自己的重量wi和自己的强壮程度si
一头牛的风险值:它头上所有牛的总重量(不包括它自己)减去它的身体强度,
风险值越大,这头牛撑不住的可能性就越高
你的任务是确定牛的排序,使得所有牛的风险值中最大值尽可能的小
输入:
第一行输出牛的数量N
接下来N行,每行输入两个整数,表示牛的重量wi和牛的强壮程度si
输出:最大风险值的最小可能值
数据范围:1<= N <50000 1<= wi <= 10000 1<= si <= 10^9
*/
#include <iostream>
#include <algorithm>
using namespace std;
typedef pair<int, int> PII;
const int N = 50010;
int n;
PII cow[N];
int main()
{
scanf("%d", &n);
for(int i = 0; i < n; i ++)
{
int w, s;
scanf("%d%d", &w, &s);
// 思考:为什么要这么存储 (便于排序)
cow[i] = {w + s, w};
}
sort(cow, cow + n);
int res = -2e9, sum = 0;// sum:当前牛之上所有牛的重量
for(int i = 0; i < n; i ++)
{
int w = cow[i].second, s=cow[i].first - w;
res = max(res, sum - s);
sum += w;
}
printf("%d\n", res);
return 0;
}
总结
提示:这里对文章进行总结:
💕💕💕