平衡的选择题
最优解
考虑动态规划,用表示前
题的选项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;
}
查看9道真题和解析