首页 > 试题广场 >

01串的价值

[编程题]01串的价值
  • 热度指数:3199 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
给出一个只包含 0 和 1 的 01 串 s ,下标从 1 开始,设第 i 位的价值为 vali ,则价值定义如下:

1. i=1时:val1 = 1
2. i>1时:
2.1 若 si ≠ si-1 , vali = 1
2.2 若 si = si-1 , vali = vali-1 + 1
字符串的价值等于 val1 + val2 + val3 + ... + valn

你可以删除 s 的任意个字符,问这个串的最大价值是多少。

输入描述:
第一行一个正整数 n ,代表串长度。
接下来一行一个 01 串 s 。
1 ≤ n ≤ 5,000


输出描述:
输出一个整数代表答案
示例1

输入

6
010101

输出

7

说明

删除后的串为0001或0111时有最大价值 
示例2

输入

20
11111000111011101100

输出

94
示例3

输入

4
1100

输出

6
import java.util.Scanner;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int original = in.nextInt();
        String originalStr = in.next();
        String currentStr = getCurrentStr(originalStr);
        int length = currentStr.length();
        int[] currentArrays = new int[length];
        fillArrays(currentStr, currentArrays);
        System.out.println(sumVal(length, currentArrays));
    }

    public static void fillArrays(String currentStr, int[] currentArrays) {
        char[] chars = currentStr.toCharArray();
        for (int i = 0; i < currentArrays.length; i++) {
            currentArrays[i] = chars[i];
        }
    }

    public static String getCurrentStr(String originalStr) {
        int count1 = 0;
        int count0 = 0;
        char[] chars = originalStr.toCharArray();
        for (int i = 0; i < chars.length; i++) {
            if ('1' == chars[i]) {
                count1++;
            } else {
                count0++;
            }
        }

        if (count0 >= count1) {
            originalStr = removeStr('1', '0', originalStr);
        } else {
            originalStr = removeStr('0', '1', originalStr);
        }
        return originalStr;
    }

    public static String removeStr(char removed, char reserved,
                                   String originalStr) {
        int firstIndex = originalStr.indexOf(reserved);
        String firstStr = "";
        if (firstIndex != 0) {
            firstStr = originalStr.substring(0, firstIndex);
        }
        int lastIndex = originalStr.lastIndexOf(reserved);
        String secondStr = originalStr.substring(firstIndex, lastIndex + 1);
        String thirdStr = "";
        if (lastIndex != originalStr.length() - 1) {
            thirdStr = originalStr.substring(lastIndex + 1);
        }
        secondStr = secondStr.replaceAll(String.valueOf(removed), "");
        originalStr = new StringBuilder().append(firstStr).append(secondStr).append(
            thirdStr).toString();
        return originalStr;
    }

    public static int sumVal(int length, int[] arrays) {
        int sum = 0;
        for (int i = 1; i < length + 1; i++) {
            sum += getVal(i, arrays);
        }
        return sum;
    }

    public static int getVal(int i, int[] arrays) {
        if (i == 1) {
            return 1;
        }
        if (arrays[i - 1] != arrays[i - 2]) {
            return 1;
        }
        return getVal(i - 1, arrays) + 1;
    }
}
发表于 2023-07-07 08:28:58 回复(0)
放个java版本的动态规划。dp[i][j][0] 表示到了第i位,上一位的是0,积累的价值为j,dp[i][j][1]表示到了第i位,上一位是1,积累的价值为j。计算状态转移方程,最后打印的答案是最后一位所有积累价值的最大值,答案测试案例确实有问题,别的楼层也提到了,可以自行检验。
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        in.nextLine();
        String s = in.nextLine();
        int[] array = new int[n];
        for (int i = 0; i < n; i++) {
            array[i] = s.charAt(i) - '0';
        }

        int[][][] dp = new int[n][n + 1][2];

        dp[0][1][array[0]] = 1;

        for (int i = 1; i < n; i++) {
            for (int j = 1; j <= n; j++) {
                if (j == 1) {
                    for (int k = 0; k < n; k++) {
                        if (array[i] == 0) {
                            dp[i][1][0] = Math.max(dp[i][1][0], dp[i - 1][k][1] + 1);
                            dp[i][1][1] = dp[i - 1][1][1];
                        } else {
                            dp[i][1][0] =  dp[i - 1][1][0];
                            dp[i][1][1] = Math.max(dp[i][1][1], dp[i - 1][k][0] + 1);
                        }

                    }
                } else {
                    if (array[i] == 0) {
                        if (dp[i - 1][j - 1][0] != 0) {
                            dp[i][j][0] = dp[i - 1][j - 1][0] + j;
                        }
                        dp[i][j][1] = dp[i - 1][j][1];
                    } else {
                        dp[i][j][0] = dp[i - 1][j][0];
                        if (dp[i - 1][j - 1][1] != 0) {
                            dp[i][j][1] = dp[i - 1][j - 1][1] + j;
                        }
                    }
                }
            }
        }

        int result = 0;
        for (int i = 0; i <= n; i++) {
            result = Math.max(result, dp[n - 1][i][0]);
            result = Math.max(result, dp[n - 1][i][1]);
        }

        System.out.println(result);
    }
}


发表于 2023-03-26 09:21:11 回复(0)
//贪心
public int valueOf01String(String str) {
        char[] s = str.toCharArray();
        int n = s.length;
        int a = -1, b = -1; //记录第一个0和第一个1
        int c = -1, d = -1; //记录最后一个0和最后一个1
        int cnt0 = 0, cnt1 = 0;//记录0 和1的个数
        for(int i = 0; i < n; i++) {
            if (a == -1 && s[i] == '0') a = i;
            if (b == -1 && s[i] == '1') b = i;
            if (s[i] == '0' && i > c) c = i;
            if (s[i] == '1' && i > d) d = i;
            if (s[i] == '0') cnt0++;
            else cnt1++;
        }
        return Math.max(C(cnt0) + C(a) + C(n - c - 1), C(cnt1) + C(b) + C(n - d - 1));
    }
    int C(int n){return n * (n + 1) / 2;}

发表于 2023-03-07 20:00:59 回复(0)
7
0001110
这个样例的实际输出应该是13吧,但是运行结果不是13却通过了
发表于 2022-04-22 18:12:26 回复(5)