题意
给你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;
}