n 種顏色玻璃珠 (n≤4),每種數量 0~7。排成一行,相同顏色相鄰形成組,組大小 1~3。相鄰組顏色不同且大小不同,首尾組也須顏色不同且大小不同。求合法排列數。
DP 狀態:dp[firstColor][firstSize][c1][c2][c3][c4][lastColor][lastSize]
含義:第一組顏色 firstColor 大小 firstSize,剩餘各顏色數量 c1..c4,最後一組顏色 lastColor 大小 lastSize 的合法排列數。
狀態總數 ≤ 4×3×8^4×4×3 ≈ 1.2M,配合記憶化可行。
ll dfs(int firstC, int firstS, int c1, int c2, int c3, int c4, int lastC, int lastS) {
if (c1==0 && c2==0 && c3==0 && c4==0) {
// 所有珠用完,檢查首尾約束
return (lastC != firstC && lastS != firstS) ? 1 : 0;
}
if (memo[...] != -1) return memo[...];
ll ans = 0;
// 嘗試添加下一組,顏色 ≠ lastC,大小 ≠ lastS,數量足夠
for (int color = 1; color <= 4; ++color) if (color != lastC) {
int* cnt = (color==1?&c1:color==2?&c2:color==3?&c3:&c4);
for (int sz = 1; sz <= 3; ++sz) if (sz != lastS && *cnt >= sz) {
*cnt -= sz;
ans += dfs(firstC, firstS, c1, c2, c3, c4, color, sz);
*cnt += sz;
}
}
return memo[...] = ans;
}
枚舉第一組顏色與大小,調用 DFS,累加總數。特判:所有數量為 0 時答案為 1 (空排列)。
dp[5][9][9][9][9][9][5][9] 替代 map,極快。