• HDU 6396(优先队列+思维)


    传送门

    题面:

    Swordsman

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
    Total Submission(s): 1441    Accepted Submission(s): 417

    Problem Description

    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.

    题目描述:

        你有最初有m种攻击属性,每种攻击属性能够攻击一个怪物的防护盾。当你的第i种攻击属性大于怪物的第i种防护盾时,你才能击穿这个盾。你能杀死这个怪物,当且仅当你把他的所有防护盾击穿。当你击杀了第i个怪物,你的每种攻击属性都会增加一定值。先有n个怪兽,问你最多能杀死多少值怪兽,且你最终的m种攻击属性为多少。

    题目分析:

        首先,我们依据贪心的策略可以知道,要想使得击杀数量越多,我们只能通过优先击杀护盾较小的怪物才行。因此,我们可以考虑使用优先队列对所有怪物的m种护盾的大小进行维护。

        我们可以开m个优先队列,第i个优先队列维护着第i个护盾的值。最开始我们将所有的怪兽(编号和第1个护盾值)存入第1号队列中,继而依次检查每一个优先队列。对于第i个队首的怪兽,如果其第i个护盾满足被杀死的条件,则将他压入第i+1个队列中。而当遍历到第m个优先队列且队首元素也满足条件,则将该怪兽弹出,代表已经杀死,并将该怪兽的经验值加上即可。

        ps:这道题普通的输入输出流都会超时,只有那种fread才不会超时。(代码中有fread的模板)

    代码:

    #include <bits/stdc++.h>
    #define maxn 500005
    using namespace std;
    int a[maxn][15];
    int b[maxn][15];
    int val[15];
    typedef pair<int,int>Pll;
    priority_queue<Pll,vector<Pll>,greater<Pll> >que[15];//一个小根堆
    //优先队列存储两个参数,一个是怪物第i个的防护值,一个是怪物的编号
    
    namespace fastIO {//fread的模板
    	#define BUF_SIZE 100000
    	//fread -> read
    	bool IOerror = 0;
    	inline char nc() {
    		static char buf[BUF_SIZE], *p1 = buf + BUF_SIZE, *pend = buf + BUF_SIZE;
    		if(p1 == pend) {
    			p1 = buf;
    			pend = buf + fread(buf, 1, BUF_SIZE, stdin);
    			if(pend == p1) {
    				IOerror = 1;
    				return -1;
    			}
    		}
    		return *p1++;
    	}
    	inline bool blank(char ch) {
    		return ch == ' ' || ch == '
    ' || ch == '
    ' || ch == '	';
    	}
    	inline void read(int &x) {
    		char ch;
    		while(blank(ch = nc()));
    		if(IOerror) return;
    		for(x = ch - '0'; (ch = nc()) >= '0' && ch <= '9'; x = x * 10 + ch - '0');
    	}
    	#undef BUF_SIZE
    };
    using namespace fastIO;
    
    int main()
    {
        int t;
        scanf("%d",&t);
        while(t--){
            int n,m;
            //scanf("%d%d",&n,&m);
            read(n),read(m);
            for(int i=1;i<=m;i++){
                //scanf("%d",&val[i]);
                read(val[i]);
                que[i]=priority_queue<Pll,vector<Pll>,greater<Pll> >();//优先队列清零
            }
            for(int i=1;i<=n;i++){
                for(int j=1;j<=m;j++){
                    //scanf("%d",&a[i][j]);
                    read(a[i][j]);
                }
                que[1].push(Pll(a[i][1],i));//将怪物的第i号护盾值压入队列
                for(int j=1;j<=m;j++){
                    //scanf("%d",&b[i][j]);
                    read(b[i][j]);
                }
            }
            int cnt=0;
            while(1){
                int tmp=cnt;
                for(int i=1;i<m;i++){
                    while(!que[i].empty()&&que[i].top().first<=val[i]){
                            //判断第i个队首元素的护盾值是否小于第i个攻击值,如果小于则将该怪兽压入第i+1个队列中
                        int id=que[i].top().second;
                        que[i].pop();
                        que[i+1].push(Pll(a[id][i+1],id));//将编号为id的怪兽的i+1的属性压入第i+1的队列中
                    }
                }
                while(!que[m].empty()&&que[m].top().first<=val[m]){//如果到达了最后一个优先队列,且队首元素仍小于第m个攻击值
                    int id=que[m].top().second;
                    que[m].pop();
                    for(int i=1;i<=m;i++){//更新每一个攻击值
                        val[i]+=b[id][i];
                    }
                    cnt++;//答案加1
                }
                if(cnt==tmp) break;
            }
            cout<<cnt<<endl;
            for(int i=1;i<m;i++){
                printf("%d ",val[i]);
            }
            printf("%d
    ",val[m]);
        }
    }
    
  • 相关阅读:
    88250 的“一分钟想法”
    88250 的“一分钟想法”
    有关在对话框上创建视图上的再探索
    jmap命令(Java Memory Map) 51CTO.COM
    要么滚回家里去,要么就拼
    悲观的思考,乐观的生活.我们既需要思考的深度,也需要生活的温度!
    对研发经理这一岗位的个人理解
    Linux Soho 兼 职 系统工程师 Email: yufeixiaoyu@gmail.com
    9月1日机器学习与自然语言处理精品班开班现场_培乐资讯_北京培乐园科技咨询有限公司
    简单的Memory leak跟踪
  • 原文地址:https://www.cnblogs.com/Chen-Jr/p/11007238.html
Copyright © 2020-2023  润新知