有两棵APP树,编号为1,2.每一秒,这两棵APP树中的其中一棵会掉一个APP.每一秒,你可以选择在当前APP树下接APP,或者迅速移动到另外一棵APP树下接APP(移动时间可以忽略不计),但由于却乏锻炼,你最多移动W次.问在T秒内,你最多能收集多少个APP.假设你开始站在1号APP树下.
Input
第1行:两个整数T(1 < = T< = 1000)和W(1 < = W< = 30)
第2…T+1行:1或2,代表每分钟掉落APP的那棵树的编号
Output
一行一个整数,代表你移动不超过W次能接住的最大APP数
Sample Input
7 2
2
1
1
2
2
1
1
Sample Output
6
记忆化搜索,将计算过的分支保存下来。
此题要考虑一开始站在2或者站在1下的两种情况
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int w = sc.nextInt();
int [] a = new int [n];
for(int i = 0; i < n; i++) {
a[i] = sc.nextInt();
}
int [][] dp1 = new int [n + 1][w + 1];
int [][] dp2 = new int [n + 1][w + 1];
System.out.println(Math.max(f(n, w, 1, dp1, a), f(n, w, 2, dp2, a)));
}
public static int f(int n, int w, int index, int[][] dp, int[] a) {
if(n == 0) {
return 0;
}
if(dp[n][w] != 0) return dp[n][w];
int i = index == 1 ? 2 : 1;
if(w == 0) {
if(index == a[n - 1]) {
dp[n][w] = f(n - 1, w, index, dp, a) + 1;
}else {
dp[n][w] = f(n - 1, w, index, dp, a);
}
}else {
if(index == a[n - 1]) {
dp[n][w] = Math.max(f(n - 1, w, index, dp, a) + 1, f(n - 1, w - 1, i, dp, a));
}else {
dp[n][w] = Math.max(f(n - 1, w, index, dp, a), f(n - 1, w - 1, i, dp, a) + 1);
}
}
return dp[n][w];
}
}