平衡的选择题
最优解
考虑动态规划,用表示前题的选项A和C的差距为,B和D的差距为.那么的范围为[-1,1],的范围为[-2,2]。因为负数不好动态规划,所以把j-1作为A和C的差距,这样的范围就是[0,2]。同理让k-2作为B和D的差距,的范围就变成了[0,4]。然后枚举第题的答案来进行转移。
当然可以写15个If去进行转移,但是也可以利用二进制位表示每个选项选与不选来转移,减少代码量和思维量。
因为的答案只取决于的答案,所以第一维可以利用滚动数组优化掉,空间复杂度
时间复杂度
int solve(int n){ int mod = 1e9 + 7; int dp[2][3][5]; memset(dp, 0, sizeof dp); int cur = 0, nxt = 1; for(int mask = 1; mask < 16; ++mask){ int A = mask&1, B = (mask>>1)&1, C = (mask>>2)&1, D = (mask>>3)&1; dp[cur][1+A-C][2+B-D]++; } for(int i = 1; i < n; ++i){ memset(dp[nxt], 0, sizeof dp[nxt]); for(int j = 0; j < 3; ++j){ for(int k = 0; k < 5; ++k){ for(int mask = 1; mask < 16; ++mask){ int A = mask&1, B = (mask>>1)&1, C = (mask>>2)&1, D = (mask>>3)&1; if(j+A-C < 3 && j+A-C >= 0 && k+B-D < 5 && k+B-D >= 0) dp[nxt][j+A-C][k+B-D] =(dp[nxt][j+A-C][k+B-D] + dp[cur][j][k])%mod; } } } swap(nxt, cur); } int ans = 0; for(int i = 0; i < 3; ++i) for(int j = 0; j < 5; ++j) ans = (ans + dp[cur][i][j])%mod; return ans; }