动态规划问题:
先声明两个数组:
-
数组
a
:存储当前状态下,所有可能的单词价值总和的计数。在每次迭代开始时,我们使用a
数组来跟踪包含当前字母之前的所有可能单词的价值总和。 -
数组
b
:在处理每个字母时,b
数组用于计算添加当前字母后所有可能的新单词的价值总和。这是通过将当前字母的价值(乘以相应的倍数,即k * i
)加到a
数组中的相应价值总和上来进行的。
在每次处理完一个字母后,我们需要将 b
数组中的新计算结果复制到 a
数组中,这样 a
数组就包含了更新后的状态。然后,我们重置 b
数组的所有元素为 0
,这样 b
数组就准备好在下一次迭代中再次使用,存储新的单词价值总和。
重置 b
数组的原因是因为在下一次迭代中,我们将再次使用 b
数组来计算添加下一个字母后的新单词价值总和。如果我们不重置 b
数组,那么之前的状态将会影响新的计算,导致结果不正确。通过将 b
数组重置为 0
,我们确保了每次计算新字母时都是从一个干净的状态开始。
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
for (int index = 0; index < n; index++) {
// 初始化数组a和b,用于存储单词的价值总和的状态
int[] a = new int[51];
int[] b = new int[51];
// 将数组a的第一个元素设置为1,表示没有字母的单词的价值总和为0
a[0] = 1;
// 遍历26个英文字母
for (int i = 1; i <= 26; i++) {
// 读取当前字母的数量
int num = scanner.nextInt();
// 如果当前字母的数量为0,则跳过当前循环,不进行任何操作
if (num == 0) continue;
// 遍历所有可能的价值总和,从0到50
for (int j = 0; j <= 50; j++) {
// 遍历当前字母可以添加到当前价值总和j的每一种情况
for (int k = 0; k <= num && (j + k * i) <= 50; k++) {
// 更新数组b,累加当前字母的价值对价值总和j的贡献
b[j + k * i] += a[j];
}
}
// 将数组b的值复制到数组a,为下一次迭代字母做准备
for (int j = 0; j <= 50; j++) {
a[j] = b[j];
// 重置数组b的值,以便下一次迭代使用
b[j] = 0;
}
}
// 计算所有价值总和小于或等于50的单词的数量
int tot = 0;
for (int i = 1; i <= 50; i++) {
tot += a[i]; // 累加数组a中每个价值总和的计数
}
// 输出所有价值总和小于或等于50的单词的总数
System.out.println(tot);
}
}
}
}