2018年第九届蓝桥杯Java程序设计本科B组决赛 防御力(编程大题)

2018年第九届蓝桥杯Java程序设计本科B组决赛个人题解汇总:

https://blog.csdn.net/daixinliangwyx/article/details/90258768

 

第六题

标题:防御力

小明最近在玩一款游戏。对游戏中的防御力很感兴趣。
我们认为直接影响防御的参数为“防御性能”,记作d,而面板上有两个防御值A和B,与d成对数关系,A=2^d,B=3^d(注意任何时候上式都成立)。
在游戏过程中,可能有一些道具把防御值A增加一个值,有另一些道具把防御值B增加一个值。
现在小明身上有n1个道具增加A的值和n2个道具增加B的值,增加量已知。

现在已知第i次使用的道具是增加A还是增加B的值,但具体使用那个道具是不确定的,请找到一个字典序最小的使用道具的方式,使得最终的防御性能最大。

初始时防御性能为0,即d=0,所以A=B=1。

【输入格式】
输入的第一行包含两个数n1,n2,空格分隔。
第二行n1个数,表示增加A值的那些道具的增加量。
第三行n2个数,表示增加B值的那些道具的增加量。
第四行一个长度为n1+n2的字符串,由0和1组成,表示道具的使用顺序。0表示使用增加A值的道具,1表示使用增加B值的道具。输入数据保证恰好有n1个0,n2个1。

【输出格式】
对于每组数据,输出n1+n2+1行,前n1+n2行按顺序输出道具的使用情况,若使用增加A值的道具,输出Ax,x为道具在该类道具中的编号(从1开始)。若使用增加B值的道具则输出Bx。最后一行输出一个大写字母E。

【样例输入1】
1 2
4
2 8
101

【样例输出1】
B2
A1
B1
E

【样例输入2】
3 0
7 11 13

000

【样例输出2】
A1
A2
A3
E

【样例说明】
对于第一组测试数据,操作过程如下:
操作  d         A              B
初始  0            1              1
B2    2         4              9
A1    3            8              27
B1   log3(29)   2^(log3(29))   29

可以证明,这个值是最大的。
对于第二组测试数据,可见无论用什么顺序,A最后总为32,即d总为5,B总为243。 

【数据规模】
对于20%的数据,字符串长度<=10000;
对于70%的数据,字符串长度<=200000;
对于100%的数据,字符串长度<=2000000,输入的每个增加值不超过2^30。


资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗  < 1000ms


请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。

所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
不要使用package语句。不要使用jdk1.7及以上版本的特性。
主类的名字必须是:Main,否则按无效代码处理。


解法:因为d=log2(A)=log3(B)这个任何时候都成立,在对A和B进行交叉操作增加x值的时候,比如先对A操作,肯定是先增加较大的ai收益最大,因为先增加大的ai会使d在这一次增加幅度较大,同时使B也增加较大,对于下一次增加B会有更好的收益;对B操作也是类似上面,也就是说,对ai和bi进行一个结构体排序,先按值的大小排序再按下标顺序(字典序)排序。当然还有注意一种情况,就是无论用什么顺序达到的收益都是一样的,这是在什么情况下会这样呢,很明显,在连续操作某一防御值的时候,不管先增加较大的还是较小的,在操作另一防御值之前,该防御值增加的总值都是一样的,对于d和另一防御值的总影响值也是一样的,因此这个时候就需要按字典序顺序操作了。

代码:

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.util.*;

public class MainB {
    public static InputReader in = new InputReader(new BufferedInputStream(System.in));
    public static PrintWriter out = new PrintWriter(System.out);
    public static int n1, n2, d, a, b, len, ka, kb, k;
    public static String s;
    public static A[] ai = new A[2000010];
    public static B[] bi = new B[2000010];
    public static int[] order;

    public static void main(String[] args) {
        d = 0;
        a = 1;
        b = 1;
        n1 = in.nextInt();
        n2 = in.nextInt();
        if (n1 == 0) s = in.nextLine();//吸取空行
        for (int i = 1; i <= n1; i++) {
            ai[i] = new A();
            ai[i].id = i;
            ai[i].value = in.nextInt();
        }
        if (n2 == 0) s = in.nextLine();
        for (int i = 1; i <= n2; i++) {
            bi[i] = new B();
            bi[i].id = i;
            bi[i].value = in.nextInt();
        }
        s = in.nextLine();
        Arrays.sort(ai, 1, n1+1);
        Arrays.sort(bi, 1, n2+1);
        len = s.length();
        ka = 1;
        kb = 1;
        for (int i = 0; i < len; i++) {
            if (s.charAt(i) == '0') {
                if (s.charAt(i) == '1') {
                    out.println("A" + ai[ka++].id);
                    out.flush();
                } else {//出现连续的0
                    order = new int[len-i+5];
                    k = 0;
                    order[k++] = ai[ka++].id;//将这一段连续的'0'对应的id存在一个数组里
                    int j = i + 1;
                    for (j = i+1; j < len; j++) {
                        if (s.charAt(j) != '0') break;
                        order[k++] = ai[ka++].id;
                    }
                    Arrays.sort(order, 0, k);//按id从小到大排(即字典序从小到大)
                    i = j - 1;//调整i,使i下一次循环是从后面第一个'1'处开始
                    for (j = 0; j < k; j++) {
                        out.println("A" + order[j]);
                        out.flush();
                    }
                }
            } else {
                if (s.charAt(i) == '0') {
                    out.println("B" + bi[kb++].id);
                    out.flush();
                } else {//出现连续的1
                    order = new int[len-i+5];
                    k = 0;
                    order[k++] = bi[kb++].id;//将这一段连续的'1'对应的id存在一个数组里
                    int j = i + 1;
                    for (j = i+1; j < len; j++) {
                        if (s.charAt(j) != '1') break;
                        order[k++] = bi[kb++].id;
                    }
                    Arrays.sort(order, 0, k);//按id从小到大排(即字典序从小到大)
                    i = j - 1;//调整i,使i下一次循环是从后面第一个'0'处开始
                    for (j = 0; j < k; j++) {
                        out.println("B" + order[j]);
                        out.flush();
                    }
                }
            }
        }
        out.println("E");
        out.flush();
        out.close();
    }

    static class A implements Comparable<A>{
        int id, value;

        @Override
        public int compareTo(A o) {
            if (o.value - this.value != 0) {
                return o.value - this.value;
            } else {
                return this.id - o.id;
            }
        }
    }

    static class B implements Comparable<B>{
        int id, value;

        @Override
        public int compareTo(B o) {
            if (o.value - this.value != 0) {
                return o.value - this.value;
            } else {
                return this.id - o.id;
            }
        }
    }

    static class InputReader {
        public BufferedReader reader;
        public StringTokenizer tokenizer;

        public InputReader(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }

        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }

        public String nextLine() {
            String str = null;
            try {
                str = reader.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

        public long nextLong() {
            return Long.parseLong(next());
        }

        public Double nextDouble() {
            return Double.parseDouble(next());
        }

        public BigInteger nextBigInteger() {
            return new BigInteger(next());
        }

    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值