算法练习记录:贪心

一、活动调度问题

题目:

假设要用很多个教室对一组活动进行调度。我们希望使用尽可能少的教室来调度所有的活动。

输入要求:

第一行为活动的个数 N(1<=N<=1 000 000) 。

接下来 N 行为 Si 和 Fi(0<=Si<Fi<=2 000 000 000) ,分别代表第 i 个活动的开始时间和结束时间。活动 i 的区间段为 [Si,Fi)

输出要求:

输出有一行 M ,为所需教室的最小数量。

测试输入:

11
1 4
3 5
0 6
5 7
3 8
5 9
6 10
8 11
8 12
2 13
12 14

测试输出:

 

5

思路

首先,按照贪心的思路,将输入的用例按照结束时间从早到晚进行排序(巧合的是给出的测试用例已经按照这个规则排好了,但我不能保证其他的用例也是这样,所以还是贪心排序了一次)

其次,从第一个活动开始做循环。

记当前的活动为i,循环碰到的下一个活动为j,如果j活动的开始时间晚于或等于i活动,那么就找到了第一种组合方式的开端,如果不满足条件,则j+1记为j继续循环,如此找完一组之后,返回一个1给记录总组数的sum变量。

注意,为了防止某一个被用过的时间段在后续被重复调用,我们需要一个数组来记录哪些活动已经被使用过了,在代码中我使用了times数组。

最后,往复循环这个过程,得到sum值,输出。

#include <iostream>
using namespace std;

int num;
int start[1000000] = { 0 };
int finish[1000000] = { 0 };
int times[1000000] = { 0 };
void Initial()//初始化,进行输入
{
    cin >> num;
    for (int i = 0; i < num; i++)
    {
        cin >> start[i];
        cin >> finish[i];
    }
}
void Rank()//贪心排序,使用了冒泡排序法,归并排序应该更快些,但是现在忘了
{
    for (int i = 0; i < num - 1; i++) {
        for (int j = i; j < num - 1 - i; j++) {
            if (finish[j] > finish[j + 1]) {
                int s = start[j], f = finish[j];
                start[j] = start[j + 1];
                finish[j] = finish[j + 1];
                start[j + 1] = s;
                finish[j + 1] = f;
            }
        }
    }
}
int Find(int x)//最重要的分组环节
{
    if (times[x] == 1)//如果通过查找记录数组,发现该活动已经使用,则返回0
        return 0;
    int i = x;
    bool flag = true;//flag用于将每个分组的最后一个活动在记录数组中对应的值,置零
    while ( i < num ) {
        for (int j = i + 1; j < num; j++) {
            if (start[j] >= finish[i] && times[j] == 0) {
                times[j] = 1;
                i = j;
                flag = true;
                break;
            }
            else
                flag = false;
        }
        if (i == num - 1) {
            flag = false;
        }
        if (flag == false) {
            times[i] = 1;
            break;
        }
    }
    return 1;
}
int main()
{
    Initial();
    Rank();
    int sum = 0;
    for (int i = 0; i < num; i++) {
        sum += Find(i);
    }
    cout << sum << endl;
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
程序 = 数据结构 + 算法  程序是为了解决实际问题而存在的。然而为了解决问题,必定会使用到某些数据结构以及设计一个解决这种数据结构的算法。如果说各种编程语言是程序员的招式,那么数据结构和算法就相当于程序员的内功。编程实战算法,不是念PPT,我们讲的就是实战与代码实现与企业应用。程序 = 数据结构 + 算法                ——图灵奖得主,计算机科学家N.Wirth(沃斯)作为程序员,我们做机器学习也好,做python开发也好,java开发也好。有一种对所有程序员无一例外的刚需 —— 算法与数据结构日常增删改查 + 粘贴复制 + 搜索引擎可以实现很多东西。同样,这样也是没有任何竞争力的。我们只可以粘贴复制相似度极高的功能,稍复杂的逻辑没有任何办法。语言有很多,开发框架更是日新月异3个月不学就落后我们可以学习很多语言,很多框架,但招聘不会考你用5种语言10种框架实现同一个功能。真正让程序员有区分度,企业招聘万年不变的重点 —— 算法与数据结构。算法代表程序员水平的珠穆朗玛。如果说各种编程语言是程序员的招式,那么数据结构和算法就相当于程序员的内功。 想写出精炼、优秀的代码,不通过不断的锤炼,是很难做到的。 开这个系列的目的是为了自我不断积累。不积跬步无以至千里嘛。
程序猿可能都知道 数据结构 + 算法 = 程序 ,慧眼识金的人懂得下下载这本算法导论的想必也知道它的经典,这是本清晰度还不错的pdf版本,外面好多资源,但都有内容不全的问题,这本是难得的全书,不用费力下载part 1234...了,分享给大家 《算法导论》((美国)Cormen)[PDF] 第二版,2006年出版的 目录: 第一部分 基础知识 引言 第1章 算法在计算中的作用 1.1 算法 1.2 作为一种技术的算法 第2章 算法入门 2.1 插入排序 2.2 算法分析 2.3 算法设计 2.3.1 分治法 2.3.2 分治法分析 第3章 函数的增长 3.1 渐近记号 3.2 标准记号和常用函数 第4章 传归式 4.1 代换法 4.2 递归树方法 4.3 主方法 4.4 主定理的证明 4.4.1 取正合幂时的证明 4.4.2 上取整函数和下取整函数 第5章 概率分析和随机算法 5.1 雇用问题 5.2 指示器随机变量 5.3 随机算法 5.4 概率分析和指示器随机变量的进一步使用 5.4.1 生日悖论 5.4.2 球与盒子 5.4.3 序列 …… 第二部分 排序和统计学 引言 第6章 堆排序 第7章 快速排序 第8章 线性时间排序 第9章 中位数和顺序统计学 第三部分 数据结构 第10章 基本数据结构 第11章 散列表 第12章 二叉查找树 第13章 红黑树 第14章 数据结构的扩张 第四部分 高级设计和分析技术 导论 第15章 动态规划 第16章 贪心算法 第17章 平摊分析 第五部分 高级数据结构 概述 第18章 B树 第19章 二项堆 第20章 斐波那契堆 第21章 用于不相交集合的数据结构 第六部分 图算法 引言 第22章 图的基本算法 第23章 最小生成树 第24章 单源最短路径 第25章 每对项点间的最短路径 第26章 最大流 第七部分 算法研究问题选编 引言 第27章 排序网络 第28章 矩阵运算 第29章 线性规划 第30章 多项式与快速傅里叶变换 第31章 有关数论的算法 第32章 字符串匹配 第33章 计算几何学 第34章 NP完全性 第35章 近似算法 第八部分 附录:数学基础知识 引言 A 求和 B 集合等离散数学结构 C 计数和概率 参考文献 索引

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值