一.题目
给出一个只包含 0 和 1 的 01 串 s ,下标从 1 开始,设第 i 位的价值为 vali ,则价值定义如下:
-
i=1时:val1 = 1
-
i>1时:
2.1 若 si ≠ si-1 , vali = 1
2.2 若 si = si-1 , vali = vali-1 + 1
字符串的价值等于 val1 + val2 + val3 + ... + valn
你可以删除 s 的任意个字符,问这个串的最大价值是多少。
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 256M,其他语言512M
输入描述:
第一行一个正整数 n ,代表串长度。
接下来一行一个 01 串 s 。
1 ≤ n ≤ 5,000
输出描述:
输出一个整数代表答案
示例1
输入例子:
6
010101
输出例子:
7
例子说明:
删除后的串为0001或0111时有最大价值
示例2
输入例子:
20
11111000111011101100
输出例子:
94
解答:
import java.util.Scanner;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
String s = in.next();
char[] ss = new char[n + 1];
for(int i = 0;i < n; i ++) {
ss[i] = s.charAt(i);
}
int[] val = new int[n + 1];
val[0] = 1;
for(int i = 1;i < n;i ++) {
val[i] = val[i - 1] + 1;
int cnt = 1;
for(int j = i - 1;j >= 0; j --) { // 从后往前遍历
if(ss[j] == ss[i]) cnt++;
else {
val[i] = Math.max(val[i], val[j] + cnt *(cnt + 1) /2); // 这是关键点
}
}
val[i] = Math.max(val[i], cnt *(cnt + 1) /2); // 如果后面连续的字符价值更大则更新
}
System.out.println(val[n-1]);
}
}
在后面复习的时候,发现自己一直跳到一个坑里面,就是for(int j = i -;j >= 0;j--这个地方,这其实就像动态规划,我老是不记得这里是从后往前去遍历,如果你是从前往后这就会导致有的重复遍历到,所以答案就会变大。我就是总是觉得要从前往后,答案就会变大。