XTUOJ1090校园活动(经典贪心)

校园活动

Accepted : 18 Submit : 73
Time Limit : 1000 MS Memory Limit : 65536 KB

Description

校园文化节的时候,Bob被好友推荐到学校当志愿者。学校一共有n个活动,每个活动有一个开始时间s和一个结束时间t(包括时间s和时间t)。每个活动开始时,这个活动的负责人就会去找空闲的志愿者帮忙。因为Bob特别有能力,活动负责人都会优先喊他去帮忙。也就是说,只要Bob有空,就会被人叫去帮忙。当然,同一时间,Bob只能去一个活动帮忙。而活动负责人在活动开始以后会非常忙而不会注意是否有人离开。所以只要过了开始时间Bob可以随时离开这个活动。然而熟悉一个新活动所需要花费的代价很大,所以Bob宁愿一直呆在一个已经熟悉了的活动也不愿更换动。Bob是个非常聪明的人,所以他可能会中途退出某个活动参加另一个活动来避开更多的活动。

Input

         第一行为一个正整数,表示样例的数目。对于每一个测试样例的第一行为一个正整数n(0<n<100000),表示活动的数目,接下来的n行中的第i(1<=i<=n)行由两个正整数Si、Ti(0<S<=T<1000000)组成,分别表示第i个活动的开始时间和结束时间。

Output

         对于每一个测试样例,输出Bob最少需要参加的活动数。

Sample Input

4

1

1 10

2

5 7

1 5

2

1 5

6 7

4

1 15

9 25

6 17

20 30

Sample Output

1

1

2

2

Hint

对于第二个样例,Bob被叫去活动2,完成活动2后,时间点为5,没有符合条件的活动了。

对于第四个样例,Bob先去活动1;最后他可以在中途出来去活动2,或者等活动1完成以后,去活动4。这样只需要去2个活动。

题意: 给你n个活动区间,可能一个活动区间还没结束另一个活动就开始了,策略就是你可以选择跳或者不跳,从而使自己尽量少的参加活动。


这个题是模拟赛的时候碰到的题,当时和hz讨论了很久,但由于当时思路不清晰没能A,后来仔细想了一下举了一些特例,找出来最佳贪心策略,然后果断AC。


思路:具体贪心策略,对于每个活动,有两种选择一个是跳出这个活动和不跳出这个活动,不管如何选择count总会加一,那么就要看跳出好,还是不跳等这个活动结束然后进入下一个活动好,那么我们不管具体是多少,就选择他们之中结束时间晚的。那么这样就可以从局部最优解推出整体最优解了。

同时,还要注意结束边界的控制,如果一个活动的包括了最后一个活动的话,那么两种情况都不用选了直接等它结束就可以了。

     特例:1—5   2—8  6—10  9—11  这个情况下肯定选择2-8和6-10中结束时间晚的那个

Code:

#include <stdio.h>
#include <algorithm>
using namespace std;
struct node{
    int s,e;
}a[100000];

bool cmp(node a,node b)                     //按开始时间小到大,结束时间大到小排序
{
    if(a.s<b.s)
        return true;
    else if(a.s==b.s&&a.e>b.e)
            return true;
    return false;
}

int main()
{
    int t,n;
    scanf("%d",&t);
    while(t--)
    {
        int i,edge,max,j,count=1;
        scanf("%d",&n);
        for(i=0;i<n;i++)
            scanf("%d%d",&a[i].s,&a[i].e);
        sort(a,a+n,cmp);
        edge=a[n-1].s;                          //边间设为开始时间最晚的那个
        max=0;
        for(i=0;i<n;)
        {
            int k;
            if(a[i].e>=edge)                    //如果当前进入的活动结束时间包括了edge那么久这个活动结束就行了
                break;
            else
            {
                for(j=i+1;i<n;j++)                 //否则开始找这个活动包括的活动中能到达最晚的时候
                {
                    if(a[j].s>a[i].e)
                        break;
                    if(a[j].e>max)
                    {
                        max=a[j].e;
                        k=j;
                    }
                }
                if(a[j].e>max)                      //和这个活动不包括的下一个活动相比选最晚的那个
                {
                    max=a[j].e;
                    k=j;
                }
            }
            i=k;                                    //然后进入那个活动,继续循环
            count++;
        }
        printf("%d\n",count);
    }
    return 0;
}

贪心问题,一定要思路清晰,找特殊案例很重要啊。



















  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值