题目链接 n个怪物,每个怪物都有5个属性,只有每种属性都比怪物高的时候才能打败这个怪物,同时每种属性都会提升一点。问最终最多能杀掉多少怪物。
贪心求解,不过贪心的姿势不是很好想。建5个优先队列,一开始的时候把所有的怪物都扔到第一个优先队列里面, 如果属性1高于 这个怪物,就把这个怪物从队列1中拿出来,扔到第2个优先队列里面。依此类推。然后在第5个队列中拿出怪物的时候就表示这个怪物可以被打死,将每项属性加上相应的值。
此题还有一个坑的地方就是输入数据的规模巨大。。scanf是会t的,普通的快速读入貌似有巨巨卡到了TLE的边缘,然而我等自带大常数的选手自然也是t了的。。这里需要采用一种更强大的输入挂。
蒟蒻用了输入挂仍然跑了499ms的垃圾代码:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <queue>
#include <map>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 100050;
const ll INF = (1LL << 62) - 1;
const double eps = 1e-8;
const ll mod = 1000000007;
int t, n, k, v[6];
int a[maxn][6], b[maxn][6];
priority_queue<pair<int, int>, vector<pair<int, int> >, greater<pair<int, int> > >q[6];
namespace IO
{
const int MX = 4e7;
char buf[MX]; int c, sz;
void Begin()
{
c = 0;
sz = fread(buf, 1, MX, stdin);
}
inline bool read(int &t)
{
while(c < sz && buf[c] != '-' && (buf[c] < '0' || buf[c] > '9')) c++;
if(c >= sz) return false;
bool flag = 0; if(buf[c] == '-') flag = 1, c++;
for(t = 0; c < sz && '0' <= buf[c] && buf[c] <= '9'; c++) t = t * 10 + buf[c] - '0';
if(flag) t = -t;
return true;
}
}
int main()
{
IO :: Begin();
IO :: read(t);
while(t--)
{
IO :: read(n), IO :: read(k);
for(int i = 1;i <= 5;i++) {while(!q[i].empty()) q[i].pop();}
for(int i = 1;i <= k;i++) IO :: read(v[i]);
for(int i = 1;i <= n;i++)
{
for(int j = 1;j <= k;j++) IO :: read(a[i][j]);
for(int j = 1;j <= k;j++) IO :: read(b[i][j]);
}
for(int i = 1;i <= n;i++)
q[1].push(make_pair(a[i][1], i));
bool flag = 1;
int ans = 0;
while(flag)
{
flag = 0;
for(int i = 1;i <= k;i++)
{
while(!q[i].empty())
{
int u = q[i].top().first, id = q[i].top().second;
if(v[i] < u) break;
if(i == k)
{
flag = 1;
ans++;
for(int j = 1;j <= k;j++)
v[j] += b[id][j];
}
else q[i + 1].push(make_pair(a[id][i + 1], id));
q[i].pop();
}
}
}
printf("%d\n", ans);
for(int i = 1;i <= k;i++)
printf("%d%c", v[i], i == k ? '\n' : ' ');
}
return 0;
}