青训营笔记之Cion 勒索病毒的最大收益 | 豆包MarsCode AI刷题

73 阅读3分钟

问题描述

小S在处理一个安全事故时发现,Cion 勒索病毒攻击了公司的数据库,对数据进行了加密,并且要求支付Cion币来解锁。为了最大化从解锁过程中获得的Cion币,小S可以对留下的01字符串进行操作,但需遵循严格的规则:

  1. 使用一个0替换子串00,获得a枚Cion币。
  2. 使用一个1替换子串11,获得b枚Cion币。
  3. 删除一个0,支付c枚Cion币。

操作的难点在于,连续两次操作的编号不能具有相同的奇偶性。

求你可以获得的最大 Cion 币是多少。


测试样例

样例1:

输入:n = 5, a = 2, b = 2, c = 1, s = "01101"
输出:3

样例2:

输入:n = 6, a = 4, b = 3, c = 5, s = "110001"
输出:11

样例3:

输入:n = 6, a = 3, b = 2, c = 1, s = "011110"
输出:4

样例4:

输入:n = 4, a = 1, b = 3, c = 2, s = "1111"
输出:3

样例5:

输入:n = 3, a = 2, b = 2, c = 1, s = "000"
输出:2

解题思路

经分析可知,若字符串有连续0或者连续1应尽可能多的进行操作1和操作2,从而可将字符串中的“00”转换为“0”,“11”转换为“1”,如果操作3的支付金额小于操作2的获得金额,对于字符串中“101”的情况可以通过一次操作3和操作2将其转换为“1”,否则不予处理。模拟过程中需留意操作2和操作1、3必须交替进行。

算法步骤

  1. 初始化变量

    • waste0:用于统计单个 0 的数量。
    • count0:用于统计连续的 00 子串的数量。
    • count1:用于统计连续的 11 子串的数量。
    • counts0:用于存储连续 0 的数量。
    • start:用于标记是否在字符串的开头。
    • count:用于临时存储连续 0 的数量。
  2. 遍历字符串

    • 从第一个字符开始遍历到倒数第二个字符。
    • 如果当前字符和下一个字符都是 0,则增加 count0 或 count 的计数。
    • 如果当前字符是 0,但下一个字符不是 0,则将 count 添加到 counts0 列表中,并重置 count
    • 如果当前字符是 1,并且下一个字符也是 1,则增加 count1 的计数。
  3. 处理最后一个字符

    • 如果最后一个字符是 0,则增加 waste0 的计数,并更新 count0
  4. 计算总收益

    • 计算 total0,即所有连续 0 的数量之和。
  5. 计算最大收益

    • 初始化 maxProfit 为 0。
    • 遍历所有可能的操作组合(替换 00 和 11 子串的数量)。
    • 计算每种操作组合的收益,并根据奇偶性限制选择最优的操作组合。
    • 更新 maxProfit
  6. 返回最大收益

    • 返回计算得到的最大收益。

代码实现

import java.util.*;
public class Main {
    public static int solution(int n, int a, int b, int c, String s) {
        int waste0 = 0, count0 = 0, count1 = 0;
        List<Integer> counts0 = new ArrayList<>();
        boolean start = true, num1 = false, num0 = false;
        int count = 0;
        for (int i = 0; i < n - 1; i++) {
            if (s.charAt(i) == '0' && s.charAt(i) == s.charAt(i + 1)) {
                if (start)
                    count0++;
                else
                    count++;
            } else if (s.charAt(i) == '0') {
                if (start)
                    waste0++;
                else {
                    counts0.add(count);
                    count = 0;
                }
            } else {
                start = false;
                if (s.charAt(i) == '1' && s.charAt(i) == s.charAt(i + 1)) {
                    count1++;
                }
            }

        }
        if (s.charAt(n - 1) == '0') {
            waste0++;
            if (!start) count0 += count;
        } 
        int res = 0;
        Collections.sort(counts0);
        int total0 = count0;
        for(int i = 0; i < counts0.size(); i++){
          total0 += counts0.get(i);
        }
        if (c >= b) {
            if(count1 > total0) res = total0 * a + total0 * b + b;
            else if(count1 == total0) res = total0 * a + total0 * b;
            else res = count1 * ( a + b) + a;
        } else {
            if(count1 > total0 + waste0) res = total0 *(a + b) + b + (waste0 + counts0.size() * (b - c));
            else if(count1 > total0) res = total0 *(a + b) + b + (count1 - total0 - 1 +counts0.size() *(b - c));
            else if(count1 == total0) res = total0 * a + count1 * b + (counts0.size() *(b - c));
            else if(count1 >= total0 - count0) res =  count1*(a + b) + a + counts0.size()*(b - c);
            else{
                for(int i = 0; i < counts0.size(); i++){
                    int cnt = counts0.get(i);
                    if(count1 >= cnt){
                        count1 -= cnt;
                        res += cnt * (a + b) + b - c;
                    }
                    else res +=  count1 * ( a + b) + a;
                }
            }
        }
        return res;
    }

}