卡牌翻面求和问题解题心得|豆包MarsCode AI刷题

118 阅读3分钟

以下是用C语言解决上述问题的代码: c #include <stdio.h> #include <stdlib.h> #define MOD 1000000007 int numOfWays(int n, int* a, int* b) { int dp[n + 1][3]; // 初始化动态规划数组 for (int i = 0; i <= n; i++) { for (int j = 0; j < 3; j++) { dp[i][j] = 0; } } dp[0][0] = 1; for (int i = 1; i <= n; i++) { // 选择正面的情况 dp[i][(dp[i - 1][0] + a[i - 1]) % 3] += dp[i - 1][0]; dp[i][(dp[i - 1][1] + a[i - 1]) % 3] += dp[i - 1][1]; dp[i][(dp[i - 1][2] + a[i - 1]) % 3] += dp[i - 1][2]; // 选择背面的情况 dp[i][(dp[i - 1][0] + b[i - 1]) % 3] += dp[i - 1][0]; dp[i][(dp[i - 1][1] + b[i - 1]) % 3] += dp[i - 1][1]; dp[i][(dp[i - 1][2] + b[i - 1]) % 3] += dp[i - 1][2]; // 取模操作 for (int j = 0; j < 3; j++) { dp[i][j] %= MOD; } } return dp[n][0]; } 你可以使用以下方式调用这个函数: c int main() { int n; scanf("%d", &n); int* a = (int*)malloc(n * sizeof(int)); int* b = (int*)malloc(n * sizeof(int)); for (int i = 0; i < n; i++) { scanf("%d", &a[i]); } for (int i = 0; i < n; i++) { scanf("%d", &b[i]); } int result = numOfWays(n, a, b); printf("%d\n", result); free(a); free(b); return 0; } 解题心得 在解决这道关于卡牌选择使得数字和能被3整除的C语言编程问题时,我经历了一系列的思考和实践过程,也收获了不少宝贵的经验。 首先,明确这是一个动态规划问题。看到要从众多卡牌的正反两面选择,并且要满足所有向上数字之和能被3整除的条件,就联想到动态规划那种通过子问题的最优解逐步推导出全局最优解的思路。 在实现过程中,定义了二维数组dp来存储中间状态。其中dp[i][j]表示考虑前i张卡牌,当前数字和除以3余数为j的方案数。初始化dp[0][0]为1,因为当没有卡牌选择时,数字和为0,能被3整除,这是一种初始的合法状态。 然后,在循环遍历每张卡牌时,分别考虑选择正面和背面的情况。对于选择正面,通过之前的状态dp[i - 1][k]k为0、1、2)来更新当前状态dp[i][(dp[i - 1][k] + a[i - 1]) % 3],意思是在前i - 1张卡牌某种余数状态下,加上当前卡牌正面数字后的新余数状态的方案数要累加。同理,对于选择背面也进行类似的更新操作。 在每一轮更新完dp数组后,都要进行取模操作,这是为了防止方案数过大超出数据类型范围,保证结果符合题目要求对1000000007取模。 整个解题过程让我更加深刻地理解了动态规划的核心思想,即通过合理定义状态和状态转移方程来解决复杂的组合问题。同时,也让我意识到在处理可能出现大数的情况时,取模操作的重要性,它能保证程序在正确的数值范围内运行,得到准确的结果。这次解题经历对我今后处理类似的动态规划和数值处理相关的编程问题都有着很好的借鉴作用。