Swordsman HDU - 6396(优先队列+输入外挂)

Swordsman HDU - 6396

Lawson is a magic swordsman with k kinds of magic attributes v1,v2,v3,…,vk. Now Lawson is faced with n monsters and the i-th monster also has k kinds of defensive attributes ai,1,ai,2,ai,3,…,ai,k. If v1≥ai,1 and v2≥ai,2 and v3≥ai,3 and … and vk≥ai,k, Lawson can kill the i-th monster (each monster can be killed for at most one time) and get EXP from the battle, which means vj will increase bi,j for j=1,2,3,…,k
.
Now we want to know how many monsters Lawson can kill at most and how much Lawson’s magic attributes can be maximized.
Input
There are multiple test cases. The first line of input contains an integer T, indicating the number of test cases. For each test case:
The first line has two integers n and k (1≤n≤105,1≤k≤5).
The second line has k non-negative integers (initial magic attributes) v1,v2,v3,…,vk.
For the next n lines, the i-th line contains 2k non-negative integers ai,1,ai,2,ai,3,…,ai,k,bi,1,bi,2,bi,3,…,bi,k.
It’s guaranteed that all input integers are no more than 109 and vj+∑i=1nbi,j≤109 for j=1,2,3,…,k.

It is guaranteed that the sum of all n ≤5×105
.
The input data is very large so fast IO (like fread) is recommended.
Output
For each test case:
The first line has one integer which means the maximum number of monsters that can be killed by Lawson.
The second line has k integers v′1,v′2,v′3,…,v′k and the i-th integer means maximum of the i
-th magic attibute.
Sample Input

1
4 3
7 1 1
5 5 2 6 3 1
24 1 1 1 2 1
0 4 1 5 1 1
6 0 1 5 3 1

Sample Output

3
23 8 4

Hint

For the sample, initial V = [7, 1, 1]
① kill monster #4 (6, 0, 1), V + [5, 3, 1] = [12, 4, 2]
② kill monster #3 (0, 4, 1), V + [5, 1, 1] = [17, 5, 3]
③ kill monster #1 (5, 5, 2), V + [6, 3, 1] = [23, 8, 4]
After three battles, Lawson are still not able to kill monster #2 (24, 1, 1)
because 23 < 24.

题意:

一个人有k个魔法属性,n个怪兽每个怪兽也有k个防御属性,如果这个人的k个属性都大于某个怪兽的相应属性的话,就可以杀掉这个怪兽,然后人的k个属性加上相应的经验值,问最多杀多少怪兽,最终的人的属性值skr啥

分析:

可以开k个优先队列,第i个优先队列代表怪兽第i个属性值,按照从小到大顺序排列。

一开始我们先把每个怪兽的第一个属性值全部放进去,然后开始while循环检查,那一次发现一圈检查下来没有杀死一只怪兽说明以后也不会杀死怪兽了,就可以停止了

那么每次循环怎么检查呢?

从1-k每个优先队列开始从头检查,如果这个属性值满足条件,那么出队,将下一属性放入相应队列,然后继续往后检查,如果能检查到最后一个及第k个属性,并且也满足条件,说明可以成功杀死一只,计数加1,出队,如果检查到中间就没有满足的了,就停止就可以了,后面根本不用看了,因为有这个坎挡着过不去

如果学过了OS之后可以发现有点类似于银行家算法

相信思路比较好像如果上面不懂的话结合代码看看也能看懂

但是重点不是这里,是时间问题,可能由于stl+数据量大的原因,超时到爆炸,之前从来没有意识到过输入外挂的重要性,也没用过,也没碰到过这样的题目卡时间卡成这样,不但要使用输入外挂,还得使用优秀的输入外挂(恶。。。(⊙o⊙)…)

我一开始用scanf读入超时,使用kuangbin输入外挂超时

然后使用了网上博客题解的外挂,足足快了500ms可怕啊

外挂:

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;
    }
}

题解code:

#include <bits/stdc++.h>
using namespace std;
priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > > q[6];
const int K = 5;
const int N = 1e5+10;
int n,k;
int v[K+5],a[N+5][K+5],b[N+5][K+5];

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();
    int T;
    IO::read(T);
    while(T--){
        for(int i = 1; i <= 5; i++)
            while(!q[i].empty()) q[i].pop();
        IO::read(n);
        IO::read(k);
        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 ok = false;
        int cnt = 0;
        while(!ok){
            ok = true;
            for(int j = 1; j <= k; j++){
                while(!q[j].empty()){
                    int val = q[j].top().first;
                    int id = q[j].top().second;
                    if(v[j] < val) break;
                    if(j == k){
                        ok = false;
                        cnt++;
                        q[j].pop();
                        for(int l = 1; l <= k; l++) v[l] += b[id][l];
                    }
                    else{
                        q[j+1].push(make_pair(a[id][j+1],id));
                        q[j].pop();
                    }
                }
            }
        }
        printf("%d\n",cnt);
        for(int i = 1; i <= k; i++){
            printf("%d",v[i]);
            if(i == k) puts("");
            else putchar(' ');
        }
    }
    return 0;
}

大家如果直接照着我这个代码写的话会发现样例不输出东西,已提交还过了

那是因为输入外挂那么有这么一句const int MX = 4e7;这个外挂自己维护了一个stdin大小设为了4e7,意思是只有当输入达到4e7后才会输出,或者碰到EOF所以提交测评可以显示正确结果
想要看结果可以把它调小比如说4,也可以根据系统不同按ctrl+()不同系统不一样我用的Ubuntu是ctrl+D,这样就可以出结果了

猜你喜欢

转载自blog.csdn.net/codeswarrior/article/details/81664826