一、问题理解
牛客288555题要求计算选择朋友的合法排列方案数。题目规定:
有3个朋友,每个朋友要被选择恰好n次
不能连续两天选择同一个朋友
结果需要对1e9+7取模
二、算法核心:四维动态规划
前三维分别记录三个朋友被选择的次数
第四维记录最后一次选择的朋友编号
三、完整代码实现(带注释)
#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
const int MOD = 1e9 + 7; // 题目要求的模数
const int MAX_N = 100; // 题目给定的n的最大值
// dp[a][b][c][last] 表示已经选了a次朋友1,b次朋友2,c次朋友3,最后选的是last(1/2/3)的方案数
int dp[MAX_N+1][MAX_N+1][MAX_N+1][4];
int main() {
int n;
cin >> n;
memset(dp, 0, sizeof(dp)); // 初始化DP数组
// 初始状态:第一天可以选择任意一个朋友
dp[1][0][0][1] = 1; // 第一天选朋友1
dp[0][1][0][2] = 1; // 第一天选朋友2
dp[0][0][1][3] = 1; // 第一天选朋友3
// 四重循环填充DP表
for (int a = 0; a <= n; ++a) {
for (int b = 0; b <= n; ++b) {
for (int c = 0; c <= n; ++c) {
if (a + b + c == 0) continue; // 跳过全0的初始状态
for (int last = 1; last <= 3; ++last) {
if (dp[a][b][c][last] == 0) continue; // 跳过无效状态
// 尝试选择下一个朋友
for (int next = 1; next <= 3; ++next) {
if (next == last) continue; // 不能连续选同一个朋友
// 计算新的选择次数
int na = a, nb = b, nc = c;
if (next == 1) na++;
else if (next == 2) nb++;
else nC++;
// 确保不超过n次选择
if (na <= n && nb <= n && nc <= n) {
dp[na][nb][nc][next] = (dp[na][nb][nc][next] + dp[a][b][c][last]) % MOD;
}
}
}
}
}
}
// 汇总结果:所有朋友都被选了n次的总和
int result = 0;
for (int last = 1; last <= 3; ++last) {
result = (result + dp[n][n][n][last]) % MOD;
}
cout << result << endl;
return 0;
}四、关键知识点
状态设计:四维DP数组精确记录了每个朋友的选择次数和最后选择的朋友
转移条件:确保不连续选择相同朋友(next != last)
边界处理:初始状态处理三个朋友的第一天选择
模运算:每次更新状态时都及时取模,防止溢出
點擊查看更多內容
為 TA 點贊
評論
評論
共同學習,寫下你的評論
評論加載中...
作者其他優質文章
正在加載中
感謝您的支持,我會繼續努力的~
掃碼打賞,你說多少就多少
贊賞金額會直接到老師賬戶
支付方式
打開微信掃一掃,即可進行掃碼打賞哦
