hdu4864 Task(贪心)

题意

给你N个机器和M个任务, 每个任务有两个值花费时间x和难度y, 每个机器也有两个值最大工作时间x1和最大工作难度y1, 机器可以胜任某个工作的条件是:机器在时间上和难度上均大于任务,机器胜任一个工作可以拿到x*500+2*y的钱,现在问你怎么匹配才能使匹配数最大且钱数最多。 


我的想法

贪心

让机器去选任务,所选的任务一定是难度上和时间上最接近的。这样可以顺利的求出最大匹配数,但求出最大钱数就不行了。因为对于更多的钱,时间的权值大于难度,我以难度为第一关键字,时间第二关键字,无法做到以时间为主。如果再以时间做一次贪心,却不能保证匹配数最大。
我的想法是不正确的。


题解

贪心

也是贪心,但是贪的方法就不同了,有基础的不同。
这次让任务去选机器,同样希望每个任务都能选到机器。既然时间更值钱,以时间为第一关键字排序,做降序排序。机器也做这样的排序。
把所有时间大于等于任务的机器找出来,对于每个任务选取一个能完成它但难度y最小的机器来做。因为对于后面所有的任务,我们找出来的机器在时间上一定能完成,就看难度了。根据贪心的基本思想,潜力大的东西要留,所以如此。这样既能保证时间大的任务优先做,又能使各种难度的任务得到合适的分配。故其是优秀的贪心方案。


小结

做贪心题一定要想好让谁去选择。


代码

#include<vector>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxl=100010;

int n,m;
int level[110];//level[i]表示当前能处理最高难度为i的机器有几台 
struct A
{
    int x,y;
}a[maxl],b[maxl];//a机器 b任务 
bool cmp(A a1,A a2)
{
    if(a1.x!=a2.x) return a1.x>a2.x;
    return a1.y>a2.y;
}

int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        for(int i=1;i<=n;i++) scanf("%d%d",&a[i].x,&a[i].y);
        for(int i=1;i<=m;i++) scanf("%d%d",&b[i].x,&b[i].y);
        sort(a+1,a+n+1,cmp);//按时间降序,等级降序 
        sort(b+1,b+m+1,cmp);
        long long cnt=0,sum=0;
        memset(level,0,sizeof(level));
        for(int i=1,j=1;i<=m;i++)//i号任务b,j号机器a 
        {
            while(j<=n&&a[j].x>=b[i].x) level[a[j].y]++,j++;
            for(int k=b[i].y;k<=100;k++)
                if(level[k]>0)
                {
                    level[k]--;
                    cnt++;
                    sum+=500*b[i].x+2*b[i].y;
                    break;
                }
        }
        printf("%lld %lld\n",cnt,sum);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/a_bright_ch/article/details/81134546