第1部分 基础算法(提高篇)--第1章 贪心算法-1430:家庭作业

1430:家庭作业

时间限制: 1000 ms 内存限制: 65536 KB

【题目描述】
老师在开学第一天就把所有作业都布置了,每个作业如果在规定的时间内交上来的话才有学分。每个作业的截止日期和学分可能是不同的。例如如果一个作业学分为10,要求在6天内交,那么要想拿到这10学分,就必须在第6天结束前交。

每个作业的完成时间都是只有一天。例如,假设有7次作业的学分和完成时间如下:

作业号 1 2 3 4 5 6 7
期限 1 1 3 3 2 2 6
学分 6 7 2 1 4 5 1
最多可以获得15学分,其中一个完成作业的次序为2,6,3,1,7,5,4,注意可能d还有其他方法。

你的任务就是找到一个完成作业的顺序获得最大学分。

【输入】
第一行一个整数N,表示作业的数量。

接下来N行,每行包括两个整数,第一个整数表示作业的完成期限,第二个数表示该作业的学分。

【输出】
输出一个整数表示可以获得的最大学分。保证答案不超过longint范围。

【输入样例】
7
1 6
1 7
3 2
3 1
2 4
2 5
6 1
【输出样例】
15


本题和智力大冲浪类似,唯一不同的是本题要加上一步优化,防止超时。因为是保证学分尽量多,所以先按学分从大到小排序,把作业在规定期限内尽量靠后排比如说我有三个作业[ 2 6 ] [ 2 5 ] [ 2 4 ]我把第一个作业安排到2 ,第二个作业安排到 1,那么第三个作业就不用考虑了,因为没有办法继续布置了,也就是1~work[ ].t 都已经排满了,每个都需要for循环判断,很浪费时间,会超时。那么我们标记一个dislike,表示从1 ~ dislike都不可以安排作业了.

#include
#include
#include
#include
#include
#include
#include
#include
#define N 1000001
using namespace std;

int n,dislike;
long long ans;
bool vis[N],f[N];

struct node
{
    int t,w;
}work[N];

bool cmp(node x,node y)
{
    return x.w  > y.w ;
}

bool pd(int x)
{
    for(int i = work[x].t ;i >= 1;i--)
    {
        if(vis[i] == 0)
        {
            vis[i] = 1;
            return 1;
        }
    }
    dislike = work[x].t ;     //不可以继续安排作业了
    return 0;
}

int main()
{
    scanf("%d",&n);
    for(int i = 1;i <= n;i++)
        scanf("%d%d",&work[i].t ,&work[i].w );
    sort(work+1,work+n+1,cmp);
    
    memset(vis,0,sizeof(vis));
    
    for(int i = 1;i <= n;i++)
    {
        if(work[i].t < dislike) continue;  //在1~dislike区间里都不可以安排作业了
        if(pd(i)) ans += work[i].w ;
    }
    
    printf("%ld",ans);
    
    return 0;
}

你可能感兴趣的:(信息学C++,一本通)