hdu2037 今年暑假不AC(贪心,活动安排问题)

今年暑假不AC

Problem Description

“今年暑假不AC?”
“是的。”
“那你干什么呢?”
“看世界杯呀,笨蛋!”
“@#$%^&*%...”
确实如此,世界杯来了,球迷的节日也来了,估计很多ACMer也会抛开电脑,奔向电视了。
作为球迷,一定想看尽量多的完整的比赛,当然,作为新时代的好青年,你一定还会看一些其它的节目,比如新闻联播(永远不要忘记关心国家大事)、非常6+7、超级女生,以及王小丫的《开心辞典》等等,假设你已经知道了所有你喜欢看的电视节目的转播时间表,你会合理安排吗?(目标是能看尽量多的完整节目)

Input

输入数据包含多个测试实例,每个测试实例的第一行只有一个整数n(n<=100),表示你喜欢看的节目的总数,然后是n行数据,每行包括两个数据Ti_s,Ti_e (1<=i<=n),分别表示第i个节目的开始和结束时间,为了简化问题,每个时间都用一个正整数表示。n=0表示输入结束,不做处理。

Output

对于每个测试实例,输出能完整看到的电视节目的个数,每个测试实例的输出占一行。

Sample Input

12

1 3

3 4

0 7

3 8

15 19

15 20

10 15

扫描二维码关注公众号,回复: 2313478 查看本文章

8 18

6 12

5 10

4 14

2 9

0

Sample Output

5

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=2037

这是一道比较简单的贪心。

先贴代码(AC):

#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
struct A
{
    int s,e;
}a[101];
bool operator < (const A &a,const A &b)
{
    if(a.s==b.s)
        return a.s>b.s;
    return a.e<b.e;
}
int main()
{
    int n;
    while(~scanf("%d",&n)&&n)
    {
        for(int i=1;i<=n;i++)
            scanf("%d%d",&a[i].s,&a[i].e);
            sort(a+1,a+1+n);
    int j=1,sum=1;;
    for(int i=2;i<=n;i++)
    {
        if(a[i].s>=a[j].e)
        {
            j=i;
            sum++;
        }
    }
    printf("%d\n",sum);
    }
    return 0;
}

时间复杂度:快排O(nlogn)+遍历O(n)=O(nlogn);

这个题因为把计数的sum写在了输入的外面,WA了好多次才改过来,以后有循环计数的题目,建议大家把给的那组数据多测试几遍。

证明:

1、归纳法

A是S(活动集合)包含活动1的优化解,只有一个活动时,那么其中就只有活动一成立。

设A<n时,命题成立。

那么在A=n时,A'是去掉贪心策略中活动一选出来的最好的方案,第一个活动是必须要选的,所以与第一个区间相交的区间就不能在选择了。现在A'中的活动是都不会相交的,只要证明出来A'是所有解中最大的就行了。

那么假设B'是最大的,A'不是最大的,现在把活动一加回去,那么就有B(B'加活动一)的可行解大于A(A'加活动一),这个时候和A是最优的就矛盾了。所以A'是优化解。所以A就是活动一和A'。

2、替换法

贪心法选出来的时间:a1,a2,a3......

不用贪心选出来的时间:b1,b2,b3......

现在需要证明b不能比a长

a1可以替换b1,a1是所有结束时间里面最早的,所以a1.e<=b1.e

假设ai可以替换bi,则有ai.e<=bi.e的,bi.e<=b(i+1).s-->ai.e<=b(i+1).s

a(i+1)是所有和ai不冲突的电影里面结束时间最早的。这个时候ai已经把bi替换了,ai.e<=bi.e<=b(i+1).s

--->b(i+1).e>=a(i+1).所以a(i+1)可以替换b(i+1)

假如b比a长,am替换了bm,现在还有一个b(m+1),前面可以知道am和b(m+1)是不冲突的(b(m+1).s>=a(m).e),那么贪心策略一定会把它选进去,所以b不会比a长。

总结:

如果在做题的时候,我一般不会去证明(这就需要去做大量的题了),因为贪心策略对我而言不容易证明出来,所以我在做题的时候,首先是想到这个策略,然后根据该出的数据去证明他的正确性,然后自己也可以写一些数据去证明,或者找到一些数据去推翻自己的方法。差不多的时候就用贪心解一下试试吧。接下来就是去学习贪心的更多类型。有时候和动态规划很像,我现在所理解的就是动态规划是要去做选择,就需要计算重叠的子问题去保存数据,但是贪心就直接计算更新就好了,不用再去做选择。emmmmm......也不知道理解的对不对。

猜你喜欢

转载自blog.csdn.net/qq_42217376/article/details/81143548