1. 程式人生 > >HDU 4864 Task(貪心) (機器完成目標任務, 兩個權值, 小範圍打表)

HDU 4864 Task(貪心) (機器完成目標任務, 兩個權值, 小範圍打表)

Task

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 7171    Accepted Submission(s): 1891


Problem Description Today the company has m tasks to complete. The ith task need xi minutes to complete. Meanwhile, this task has a difficulty level yi. The machine whose level below this task’s level yi cannot complete this task. If the company completes this task, they will get (500*xi+2*yi) dollars.
The company has n machines. Each machine has a maximum working time and a level. If the time for the task is more than the maximum working time of the machine, the machine can not complete this task. Each machine can only complete a task one day. Each task can only be completed by one machine.
The company hopes to maximize the number of the tasks which they can complete today. If there are multiple solutions, they hopes to make the money maximum.
Input The input contains several test cases. 
The first line contains two integers N and M. N is the number of the machines.M is the number of tasks(1 < =N <= 100000,1<=M<=100000).
The following N lines each contains two integers xi(0<xi<1440),yi(0=<yi<=100).xi is the maximum time the machine can work.yi is the level of the machine.
The following M lines each contains two integers xi(0<xi<1440),yi(0=<yi<=100).xi is the time we need to complete the task.yi is the level of the task.
Output For each test case, output two integers, the maximum number of the tasks which the company can complete today and the money they will get.
Sample Input 1 2 100 3 100 2 100 1
Sample Output 1 50004

題目大意:

有n臺機器, 每臺機器都有兩個 權值,  時間和 能力;

有m 個目標  每個目標也有兩個權值  時間和 難度係數,     一天 一臺機器只能幹一個目標,問 這個n 臺機器   做多同時 能幹幾個目標, 以及 賺的利潤  利潤等於

目標時間*500+ 目標係數*2;

思路:   因為 對於利潤來說   時間因素要遠遠大於 難度係數 ; 因此 我們用 時間來排序, 當 時間相同時按照難度係數,   降序,  時間大再前面,   (目標和 機器也都要排序) 

 排序後    因為資料量是10w*10w  所以兩層for 迴圈必然超時;

 因此., 我們只用一個for迴圈,來操作,  以目標為準,  掃描 大於當前目標的所有機器,  選擇一個 能力最接近目標的 一臺機器 (貪心)  讓同等能力下,最弱的 去幹掉目標,

問題在於怎麼去找這個 最小的,  掃描必然會超時,,  所以  打表無疑是做好的,   用一個數組 記錄所有 時間比他強的   以能力作為下標 存個數;

 以目標的係數為基準, 開始掃描 找到第一個 大於等於他的機器  ,

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <queue>
#include <string>
#include <cmath>
#include <cstring>

typedef long long ll;
using namespace std;

struct machine{
    int t;
    int l;
    int flag;
}a[100010],b[100010];

int cmp2(machine a,machine b)
{
    if(a.t==b.t)
        return a.l>b.l;
    return a.t>b.t;
}

int main()
{
    int n,m;

    while(~scanf("%d %d",&n,&m))
    {
        memset(b,0,sizeof(b));
        memset(a,0,sizeof(a));
        for(int i=0;i<n;i++)
            scanf("%d %d",&a[i].t,&a[i].l);
        for(int i=0;i<m;i++)
            scanf("%d %d",&b[i].t,&b[i].l);
        sort(a,a+n,cmp2);
        sort(b,b+m,cmp2);
        ll sum=0,cont=0;
        int i,j;
    //    for(i=0;i<n;i++)
    //    {
    //        printf("<%d %d>\n",a[i].t,a[i].l);
    //    }
    //    for(i=0;i<m;i++)
    //    {
    //        printf("| %d %d |\n",b[i].t,b[i].l);
    //    }
        int c[10100];
        memset(c,0,sizeof(c));
        for(i=0,j=0;j<m;j++)
        {
            while(a[i].t>=b[j].t&&i<n)
            {
                c[a[i].l]++;
                i++;
            }
            int k=b[j].l;
            int flag=1;
            while(k<1000&&flag)
            {
                if(c[k])
                {
                    c[k]--;
                    sum+=500*b[j].t+2*b[j].l;
                    cont++;
                    flag=0;
                }
                k++;
            }
        }
        printf("%lld %lld\n",cont,sum);
    }
    return 0;
}
/*
4 5
100 4
100 3
100 2
80 5
100 1
80 3
90 2
70 4
60 3
*/


123