(贪心+并查集)家庭作业

目录

题目描述:

输入格式

输出格式

样例

输入数据 1

输出数据 1

数据范围与提示

程序步骤设计:

代码+理解:

题目描述:

老师在开学第一天就把所有作业都布置了,每个作业如果在规定的时间内交上来才有学分。

每个作业的截止日期和学分可能是不同的。例如如果一个作业学分为10,要求在 6 天内交,那么要想拿到这10学分,就必须在第6天结束前交。

每个作业都需要一天的时间完成。

例如,假设有 7 次作业的学分和完成时间如下:

作业号期限学分
116
27
332
41
524
65
761

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

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

输入格式

第一行一个整数 N,表示作业的数量;

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

输出格式

输出一个整数表示可以获得的最大学分。保证答案不超过 C/C++ 的 int 范围。

样例

输入数据 

7
1 6
1 7
3 2
3 1
2 4
2 5
6 1

输出数据 

15

数据范围与提示

对于 20% 的数据,N≤10^3;

对于 40% 的数据,N≤10^4;

对于 60% 的数据,N≤10^5;

对于 100% 的数据,N≤106,作业的完成期限均小于 7*10^5。

程序步骤设计:

1、结构体加排序(学分从大到小,期限从小到大)

2、并查集(查找天数)

3、循环枚举(最好是当天作业当天完成)

代码+理解:

#include<bits/stdc++.h>
using namespace std;
const int N=1000001;
struct Node
{
    int t,w;
}a[N];     //需要同时对学分和期限进行排序
bool cmp(Node a,Node b) //  结构体排序规则
{
    if(a.w==b.w)    return a.t<b.t; //  如果学分相同,优先做期限短的,确保完成作业,不同则直接按学分大小排
    return a.w>b.w;
}
bool b[N];//    记录有没有时间做当前作业
int l[N];// 并查集
int find(int x)//   查找上级
{
    if(l[x]!=x) l[x]=find(l[x]);
    return l[x];
}
int main()
{
    int n,ans=0;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d %d",&a[i].t,&a[i].w);//   输入
    sort(a+1,a+n+1,cmp);//  排序
    for(int i=1;i<=n;i++)   l[i]=i;//   赋初值
    for(int i=1;i<=n;i++)//    循环作业 
    {
        for(int j=a[i].t;j>=1;j=l[j])// 循环做作业的时间
            if(b[j]==0)//   当天有空
            {
                b[j]=true,l[j]--,ans+=a[i].w;// 记录并加入答案
                break;
            }
        l[a[i].t]=find(a[i].t);
    }
    printf("%d",ans);//输出
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值