[POJ][3988][贪心] Selecting courses

描述:

一个新学期来临了,学生们烦恼与选课。学生们在网络课程系统上面选课。那里有n门课,第i门课准许在时间间隔(Ai,Bi)内选择。那意味着,如果你想选第i门课,你必须在时间Ai之后和Bi之前选择它。Ai和Bi全部用分钟表示。一个学生只能每5分钟选一次课,但是他可以选择在任意时间开始选课,还有可以尝试任意多次。例如,如果你尝试在5分21秒时选课,那么你可以在10分21秒,15分21秒,20分21秒…时继续尝试。一个学生不能在同一时间选择多于一门的课。可能会发生有一个学生在尝试选课时却发现已经无课可选的情况。

请你来计算下一个学生至多能选多少门课。

输入:

不超过100组测试数据。

每组测试数据的第一行包含一个整数N。N是课程的数量 (0 < N <= 300) 。

接下来有n行。每行包含两个整数Ai和Bi (0 <= Ai < Bi <=1000),表示第i门课准许在时间间隔(Ai,Bi)内选择。

当N=0时表示输入停止。

输出:

对于每组测试数据,用一行输出一个整数,表示一个学生最多能选课程的数量。

思路:

本题思路为贪心。

简单思考可知,选课共有5种方案,分别为:在时间范围(5*k+0,5*k+1),(5*k+1,5*k+2),(5*k+2,5*k+3),(5*k+3,5*k+4),(5*k+4,5*k+5)内开始选课。

我们可以通过枚举5种方案再配合贪心思想得出正确答案。本题的贪心思想主要体现在选课的优先顺序上,优先选择结束时间早的课程。这是非常好理解的,先选了结束时间早的课程,那么结束时间晚的课程可能还有机会在下次选课时被选上,就算选不上,那也只能说明鱼和熊掌不可兼得。

代码:

#include
#include
using namespace std;
struct point
//将课程的时间范围封转在结构体中,便于利用qsort排序。 
{
    int a;
    //开始时间 
    int b;
    //结束时间 
}course[300];
int n;
int max(int a,int b) 
{
    return a>b?a:b;
}
int min(int a,int b)
{
    return a<b?a:b;
}
int cmp(const void* m,const void* n)
//比较函数,将课程按照结束时间由早到晚排序。 
{
    return (*(point*)m).b-(*(point*)n).b;
}
int solve(int start,int min_a,int max_b)
//start的值只可以为0、1、2、3、4。 
//min_a为所有课程中开始时间的最小值。
//max_b为所有课程中结束时间的最大值。 
{
    bool mark[300];
    //mark[]用于标记某节课是否被选过。 
    for(int i=0;i<n;i++)
        mark[i]=false;
    int sum=0;
    //选课数量。 
    for(int i=min_a/5*5+start;i<max_b;i+=5)
    //[0,min_a/5*5)范围内不会有课程可以选。 
        for(int j=0;j<n;j++)
            if(!mark[j]&&course[j].a<=i&&i<course[j].b)
            //遇见的第一个没被标记过且可选的课程。
            //这也意味着此课程是此时可选课程里结束时间最早的。
            //优先选择结束时间最早的课程的现实意义是,结束时间较晚的课程可能还有机会在下次选课时被选中。 
            {
                mark[j]=true;
                sum++;
                break;
            }
    return sum;
}
int main()
{
    while(scanf("%d",&n)&&n)
    {
        int min_a=1000,max_b=0;
        for(int i=0;i<n;i++)
        {
            scanf("%d%d",&course[i].a,&course[i].b);
            min_a=min(min_a,course[i].a);
            max_b=max(max_b,course[i].b);
        }
        qsort(course,n,sizeof(course[0]),cmp);
        int res=0;
        for(int i=0;i<5;i++)
            res=max(res,solve(i,min_a,max_b));
        printf("%d\n",res);
    }
}

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注