贪心 - Task - HDU - 4864

贪心 - Task - HDU - 4864

题意:

多 组 测 试 用 例 , 首 行 包 括 两 个 整 数 n 和 m , 分 别 表 示 有 n 台 机 器 , m 个 任 务 。 多组测试用例,\\首行包括两个整数n和m,分别表示有n台机器,m个任务。 nmnm

接 下 来 的 n 行 , 每 行 包 括 两 个 整 数 x i , y i , 表 示 第 i 台 机 器 的 工 作 时 间 上 限 是 x i , 工 作 难 度 上 限 是 y i 。 接下来的n行,每行包括两个整数x_i,y_i,表示第i台机器的工作时间上限是x_i,工作难度上限是y_i。 nxi,yiixiyi

再 接 着 的 m 行 , 每 行 包 括 两 个 整 数 x i , y i , 表 示 第 i 个 任 务 需 要 花 费 x i 的 时 间 , 工 作 难 度 是 y i 。 再接着的m行,每行包括两个整数x_i,y_i,表示第i个任务需要花费x_i的时间,工作难度是y_i。 mxi,yiixiyi

每 个 任 务 的 收 益 为 f ( i ) = 500 × x i + 2 × y i , ( 1 < = i < = m ) . 每个任务的收益为f(i)=500×x_i+2×y_i,(1<=i<=m). f(i)=500×xi+2×yi(1<=i<=m).

现 要 求 使 用 n 台 机 器 做 任 务 能 够 获 得 的 最 大 收 益 。 现要求使用n台机器做任务能够获得的最大收益。 使n

数据范围:
1 < = n , m < = 100000 , 0 < x i < 1440 , 0 = < y i < = 100 T i m e   l i m i t : 2000 m s , M e m o r y   l i m i t : 32768 k B 1 < =n,m <= 100000,0<x_i<1440,0=<y_i<=100\\Time \ limit:2000 ms,Memory\ limit:32768 kB 1<=n,m<=100000,0<xi<1440,0=<yi<=100Time limit2000msMemory limit32768kB

Sample Input:

1 2
100 3
100 2
100 1

Sample Output:

1 50004

分析:

由 收 益 计 算 公 式 f ( i ) = 500 × x i + 2 × y i , 容 易 发 现 x i 越 大 , 收 益 越 大 , 因 此 要 获 得 最 大 收 益 , 我 们 首 先 要 选 择 x i 更 大 的 任 务 。 由收益计算公式f(i)=500×x_i+2×y_i,容易发现x_i越大,收益越大,\\因此要获得最大收益,我们首先要选择x_i更大的任务。 f(i)=500×xi+2×yixixi

故 我 们 将 机 器 和 任 务 都 以 时 间 x i 为 第 一 关 键 字 , 难 度 y i 为 第 二 关 键 字 排 序 。 故我们将机器和任务都以时间x_i为第一关键字,难度y_i为第二关键字排序。 xiyi

这 样 我 们 从 前 到 后 考 虑 每 个 任 务 , 若 该 任 务 能 够 被 某 些 机 器 完 成 , 就 从 这 些 机 器 中 挑 选 难 度 上 限 最 低 的 一 个 去 完 成 。 这样我们从前到后考虑每个任务,若该任务能够被某些机器完成,就从这些机器中挑选难度上限最低的一个去完成。

具体落实:

用 一 个 v i s 数 组 , v i s [ k ] 统 计 能 够 完 成 难 度 为 k 的 机 器 的 数 量 。 M 表 示 机 器 参 数 , T 表 示 任 务 参 数 。 用一个vis数组,vis[k]统计能够完成难度为k的机器的数量。\\M表示机器参数,T表示任务参数。 visvis[k]kMT

双 指 针 , i 从 前 到 后 遍 历 每 个 任 务 , j 从 前 到 后 枚 举 每 个 机 器 , 若 第 j 个 机 器 的 时 间 上 限 大 于 第 i 个 任 务 的 时 间 上 限 , 则 v i s [ M [ j ] . y ] + + , 表 示 时 间 上 限 满 足 第 i 个 任 务 且 能 够 完 成 难 度 M [ j ] . y 的 机 器 数 量 增 加 1 , 同 时 指 针 j 后 移 j + + 。 双指针,i从前到后遍历每个任务,j从前到后枚举每个机器,\\若第j个机器的时间上限大于第i个任务的时间上限,则vis[M[j].y]++,\\表示时间上限满足第i个任务且能够完成难度M[j].y的机器数量增加1,同时指针j后移j++。 ijjivis[M[j].y]++iM[j].y1jj++

j 指 针 停 止 后 , f o r 循 环 k 再 从 第 i 个 任 务 的 难 度 T [ i ] . y 开 始 枚 举 , 找 到 第 一 个 难 度 上 限 大 于 等 于 T [ i ] . y 的 机 器 , 即 v i s [ k ] > 0 时 , 选 择 这 台 机 器 来 完 成 第 i 个 任 务 , b r e a k 。 j指针停止后,for循环k再从第i个任务的难度T[i].y开始枚举,找到第一个难度上限大于等于T[i].y的机器,\\即vis[k]>0时,选择这台机器来完成第i个任务,break。 jforkiT[i].yT[i].yvis[k]>0ibreak

因 为 所 有 任 务 已 按 x i 为 第 一 关 键 字 排 好 序 , 对 于 后 面 的 每 个 任 务 而 言 , v i s 统 计 的 所 有 机 器 的 时 间 上 限 都 高 于 这 些 任 务 。 因为所有任务已按x_i为第一关键字排好序,对于后面的每个任务而言,vis统计的所有机器的时间上限都高于这些任务。 xivis

所 以 我 们 都 仅 需 考 虑 难 度 , 找 到 难 度 最 低 的 一 个 能 够 完 成 任 务 机 器 即 可 。 所以我们都仅需考虑难度,找到难度最低的一个能够完成任务机器即可。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>

#define ll long long
#define P pair<int,int>
#define x first
#define y second
#define inf 0x3f3f3f3f

using namespace std;

const int N = 100010;

int n,m;
P M[N],T[N];
int vis[N];

int cal(int i)
{
    return 500*T[i].x+2*T[i].y;
}

bool cmp(P a,P b)
{
    if(a.x==b.x) return a.y>b.y;
    return a.x>b.x;
}

int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        memset(vis,0,sizeof vis);

        for(int i=1;i<=n;i++) scanf("%d%d",&M[i].x,&M[i].y);
        for(int i=1;i<=m;i++) scanf("%d%d",&T[i].x,&T[i].y);

        sort(M+1,M+n+1,cmp);
        sort(T+1,T+m+1,cmp);

        int cnt=0;
        ll res=0;
        for(int i=1,j=1;i<=m;i++)
        {
            while(M[j].x>=T[i].x&&j<=n) vis[M[j++].y]++;

            for(int k=T[i].y;k<=100;k++)
                if(vis[k])
                {
                    vis[k]--;
                    cnt++;
                    res+=cal(i);
                    break;
                }
        }
        cout<<cnt<<' '<<res<<endl;
    }

    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值