思路 :设d[i][j][k][l] 为 第i个位置还有j个炸弹未放置,且(1, i)的位置有k个雷,(3,i)的位置有l个雷,0 <= k, l <= 1时的方案总数,那么i - 1个位置还剩str[i - 1] - '0'-k-l个雷未放置,再按当前剩余j - k - l个未放置的类在i - 1的位置上放置
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
typedef long long ll;
const int maxn = 1e4 + 10;
const int INF = 1e9;
const int mod = 1e8 + 7;
using namespace std;
int T;
char s[maxn];
ll d[maxn][7][2][2];
ll dfs(int i, int j, int up, int down) {
if(i == 0 && j - up - down == 0) return d[i][j][up][down] = 1;
if(i == 0 && j - up - down != 0) return d[i][j][up][down] = 0;
ll &res = d[i][j][up][down];
if(res > -1) return res;
res = 0; j = j - up - down;
if(j < 0 || j > 2) return res;
int nxt = s[i - 1] - '0' - up - down;
if(j == 0) res += dfs(i - 1, nxt, 0, 0);
if(j == 1) res += dfs(i - 1, nxt, 0, 1);
if(j == 1) res = (res + dfs(i - 1, nxt, 1, 0));
if(j == 2) res = (res + dfs(i - 1, nxt, 1, 1));
res %= mod;
return res;
}
int main() {
scanf("%d", &T);
while(T--) {
scanf("%s", s);
int l = strlen(s) - 1, c = s[l] - '0';
memset(d, -1, sizeof(d));
int sign = 1;
for(int i = 0; i <= l; i++) {
if(i == 0 && s[i] > '4') sign = 0;
if(i == l && s[i] > '4') sign = 0;
if(s[i] > '6') sign = 0;
if(i < l && abs(s[i] - s[i + 1]) > 2) sign = 0;
}
ll ans = 0;
if(sign) {
if(c >= 0) dfs(l, c, 0, 0);
if(c >= 1) dfs(l, c, 0, 1);
if(c >= 1) dfs(l, c, 1, 0);
if(c >= 2) dfs(l, c, 1, 1);
for(int i = 0; i < 2; i++) {
for(int j = 0; j < 2; j++) {
if(d[l][c][i][j] == -1) continue;
ans = (ans + d[l][c][i][j]) % mod;
}
}
}
printf("%lld\n", ans);
}
return 0;
}
本文介绍了一种通过动态规划解决特定炸弹放置方案计数问题的算法实现。该算法使用四维状态转移方程,考虑了炸弹放置的限制条件,并通过递归方式计算所有可能的放置方案数量。
9277

被折叠的 条评论
为什么被折叠?



