贪心问题详解(c++)

时间:2024-11-21 08:16:10

目录

什么是贪心

贪心例题

排队打水问题

拦截导弹的系统数量求解


什么是贪心

贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,他所做出的是在某种意义上的局部最优解。 贪心算法不是对所有问题都能得到整体最优解,关键是贪心策略的选择,选择的贪心策略必须具备无后效性,即某个状态以前的过程不会影响以后的状态,只与当前状态有关。 贪心算法的使用前提:局部最优解一定能导致全局最优解

 

贪心例题

排队打水问题

题目描述

有n个人排队到r个水龙头去打水,他们装满水桶的时间t1,t2,...,tn为整数且各不相等,应如何安排他们的打水顺序才能使他们花费的总时间最少?

每个人打水的时间 = 排队的时间 + 实际打水的时间,本题假设一个人打好水,排在他后面的人接着打水的这个切换过程不消耗时间。

比如,有2个人A和B,他们打水的时间分别是3和2,只有1个水龙头,这时,如果A先打水,B后打水,那么A和B打水的时间分别为3、3+2(B排队3分钟)。

因此,所有人打水的总时间就是每个人的打水时间及每个人的排队时间的总和。

输入

第1行,两个整数n(1<=n<=500)和r(1<=r<=100)。
第2行,n个正整数t1,t2,...,tn,(1<=ti<=1000)表示每个人装满水桶的时间。

输出

1行,一个正整数,表示他们花费的最少总时间。

样例

输入

  1. 4 2
  2. 2 6 4 5

输出

23

 

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. int n, a[510], r, i, s = 0;
  4. int main() {
  5. cin >> n >> r;
  6. //读入每个人的打水时间
  7. for (i = 1; i <= n; i++) {
  8. cin >> a[i];
  9. }
  10. //排序:从小到大,打的快的先打
  11. sort(a + 1, a + n + 1);
  12. //从第r+1个人开始修正每个人的总打水时间
  13. //求和
  14. for (i = 1; i <= n; i++) {
  15. if (i >= r + 1) a[i] += a[i - r]; //相当于a[i]=a[i]+a[i-r];
  16. s = s + a[i];
  17. }
  18. cout << s;
  19. return 0;
  20. }

拦截导弹的系统数量求解

题目描述

某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。
假设某天雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。
输入n个导弹依次飞来的高度(给出的高度数据是不大于30000的正整数),计算如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。
比如:有8颗导弹,飞来的高度分别为
389 207 175 300 299 170 158 165
那么需要2个系统来拦截,他们能够拦截的导弹最优解分别是: 系统1:拦截 389 207 175 170 158
系统2:拦截 300 299 165

输入

两行,第一行表示飞来导弹的数量n(n<=1000)

第二行表示n颗依次飞来的导弹高度

输出

要拦截所有导弹最小配备的系统数k

样例

输入

  1. 8
  2. 389 207 175 300 299 170 158 165

输出

2

思路:

1、当导弹来袭,假设导弹高度为x,在a数组中找能拦截的系统中最矮的系统进行拦截
2、如果找不到这样的系统:开新系统拦截,将新系统的高度设为x
3、如果能找到(找到能拦截的第1套系统,就是最矮):因为导弹拦截系统的高度一定是递增的
用能拦截的第1套系统拦截,并将该系统的高度设为x,最后看要几套系统

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. //p:代表找到的能够拦截系统的下标
  4. //k:代表有几套系统
  5. //x:代表每套系统的高度
  6. int a[1100],n,i,j,x,p,k = 0;
  7. int main() {
  8. cin>>n;
  9. //循环导弹的数量
  10. for(i = 1;i <= n;i++){
  11. cin>>x;
  12. p = -1;//假设没找到
  13. //在k套系统中找第1套能拦截的系统
  14. for(j = 1;j <= k;j++){
  15. //找到第1套能拦截的系统
  16. if(a[j] >= x){
  17. p = j;
  18. break;
  19. }
  20. }
  21. //如果找到系统拦截
  22. if(p != -1){
  23. a[p] = x;
  24. }else{
  25. //开新系统
  26. k++;
  27. a[k] = x;//更新系统高度
  28. }
  29. }
  30. cout<<k;
  31. return 0;
  32. }