说在前面
今天打了场比赛有个很简单的区间贪心问题写得磕磕绊绊,因此深感几个经典的区间贪心问题还是应该重新看看并加以总结形成模板。这种问题就应该像大神们那样十几分钟内稀里哗啦的敲出来。
区间调度
区间调度呢很简单,说白了就是活动时间安排问题。最经典的莫过于杭电的hdu2037。
(例题)区间调度
Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u
Submit
Status
Practice
HDU 2037
Description
“今年暑假不AC?”
“是的。”
“那你干什么呢?”
“看世界杯呀,笨蛋!”
“@#$%^&*%…”
确实如此,世界杯来了,球迷的节日也来了,估计很多ACMer也会抛开电脑,奔向电视了。
作为球迷,一定想看尽量多的完整的比赛,当然,作为新时代的好青年,你一定还会看一些其它的节目,比如新闻联播(永远不要忘记关心国家大事)、非常6+7、超级女生,以及王小丫的《开心辞典》等等,假设你已经知道了所有你喜欢看的电视节目的转播时间表,你会合理安排吗?(目标是能看尽量多的完整节目)
Input
输入数据包含多个测试实例,每个测试实例的第一行只有一个整数n(n<=100),表示你喜欢看的节目的总数,然后是n行数据,每行包括两个数据Ti_s,Ti_e (1<=i<=n),分别表示第n=0表示输入结束,不做处理。
Output
对于每个测试实例,输出能完整看到的电视节目的出能完整看到的电视节目的个数,每个测试实例的输出占一行。
个数,每个测试实例的输出占一行。
Sample Input 14
2 9
0
Output
5
这道题通俗的解释就是说让你从一堆区间里面选其中几个,使之不出现交叉。问最多可以取的区间的数量。这种题直接套路化的记结论是最快的,贪心如果想太多很多时候就浪费时间了。
将每个区间左右端点写入结构体,并写一个cmp函数按右端点从小到大排序,之后写一个循环(贪心中必须的,很重要,贪心经常需要无脑循环和无脑遍历,而且一般都并不会超时),按下一个区间的左端点大于上一个区间的右端点进行选择,选择成功就计入总数,同时最重要的就是记得选择起点的更新,将选择起点更新为新选择区间的右端点。
以下是代码。
#include <iostream>
#include <algorithm>
using namespace std;
typedef struct A
{
int x, y;
}A;
bool cmp(A a, A b)
{
return a.y < b.y;
}
int main()
{
int n;
while (cin >> n && n)
{
A a[105];
int sum = 1;
for (int i = 0; i < n; i++)
{
cin >> a[i].x >> a[i].y;
}
sort(a, a + n, cmp);
int start = a[0].y;
for (int i = 1; i < n; i++)//循环遍历所有区间
{
if (a[i].x >= start)//if判定语句
{
start = a[i].y;//区间端点的更新
sum++;
}
}
cout << sum << endl;
}
return 0;
}