第一次多校的题目,看到不少过了就觉得是个贪心但是一直想不出贪心方案。后来看了题解才恍然大悟。。500*x+2*y,价值可以说基本上就是靠X,Y仅仅是在X相同的时候才有作用,所以只需要对TASK的时间进行降序排序,在时间相同时,按照Y降序排序。这样从头往后一个个选就是价值最高的到最低。机器同样也要这样排序,然后选择的时候要找满足条件且Y最小的。因为选择这个价值最高,Y最小可以使得后面的更有可能被匹配到。后面的机器会不会因为这台机器选了它而导致匹配数少一个呢?答案是不会,因为他已经是Y最小了,比他小就没办法选这个任务了,而且这个任务是当前价值最高的,所以当然要选这个。故贪心正确。
但是这样一个个遍历去找感觉太慢会超时,我想了个办法,这样就不用对机器进行排序了,因为X仅仅只有1440种,Y仅仅只有100种,那么就开一个二维数组,然后在输入机器数据的时候就把FLAG[ X ][ Y ]++;然后后面找的时候只需要2层FOR循环,从第X层的Y个开始往后找直到1440,而且第一次找到就是应该匹配的最优解了。
AC代码:
#include<cstdio>
#include<ctype.h>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<vector>
#include<stack>
#include<cmath>
#include<queue>
#include<set>
#include<ctime>
using namespace std;
#define NMAX 10000000
#define MOD 1000000007
#define ll __int64
typedef struct shit
{
int t,l;
}shit;
shit mach[100005],task[100005];
int cmp(const void *a, const void *b)
{
shit *s1 = (shit*)a;
shit *s2 = (shit*)b;
if(s2->t == s1->t) return s2->l - s1->l;
return s2->t - s1->t;
}
int flag[105][1450];
int main()
{
// freopen("input.txt","r",stdin);
// freopen("o1.txt","w",stdout);
int n,m,i,j,k;
while(scanf("%d%d",&n,&m) == 2)
{
memset(flag,0,sizeof(flag));
for(i = 0; i < n; i++)
{
scanf("%d%d",&mach[i].t,&mach[i].l);
flag[mach[i].l][mach[i].t]++;
}
for(i = 0; i < m; i++)
scanf("%d%d",&task[i].t,&task[i].l);
qsort(task,m,sizeof(shit),cmp);
ll ans = 0;
int num = 0;
for(i = 0; i < m; i++)
{
int gg = 0;
for(j = task[i].l; j <= 101; j++)
{
for(k = task[i].t; k <= 1450; k++)
if(flag[j][k])
{
num++;
gg = 1;
flag[j][k]--;
ans += 500*(ll)task[i].t+2*(ll)task[i].l;
break;
}
if(gg) break;
}
}
printf("%d %I64d\n",num,ans);
}
return 0;
}