HDU 5965 三维dp 或 递推

时间:2021-11-14 16:40:05

题意:= =中文题

思路一:比赛时队友想的。。。然后我赛后想了一下想了个2维dp,但是在转移的时候,貌似出了点小问题...吧?然后就按照队友的思路又写了一遍。

定义dp[i][j][k],表示第i列,放j个,剩下k个的种类数。其中j<=2, k<=2,j<=2的来源是只往上、下放。然后状态转移就是

dp[i][j][a[i] - j - k] = (dp[i][j][a[i] - j - k] + p[j] * dp[i - 1][k][j]) % mod;

//看看会不会爆int!数组会不会少了一维!
//取物问题一定要小心先手胜利的条件
#include <bits/stdc++.h>
using namespace std;
#pragma comment(linker,"/STACK:102400000,102400000")
#define LL long long
#define ALL(a) a.begin(), a.end()
#define pb push_back
#define mk make_pair
#define fi first
#define se second
#define haha printf("haha\n")
/*
定义dp[i][j][k]表示第i个人放了j个剩下k个的种类数 */
const LL mod = ;
const int maxn = 1e4 + ;
LL dp[maxn][][];
char ch[maxn];
int a[maxn];
int n;
LL p[] = {, , }; LL solve(){
memset(dp, , sizeof(dp));
for (int i = ; i <= ; i++) {
if (a[] - i > ) continue;
if (a[] - i < ) break;
dp[][i][a[] - i] = p[i];
}
for (int i = ; i <= n; i++){
for (int j = ; j <= ; j++){
for (int k = ; k <= ; k++){
if (a[i] - j - k > ) continue;
if (a[i] - j - k < ) break;///目前放入j个,dp[i-1]剩下j个
dp[i][j][a[i] - j - k] = (dp[i][j][a[i] - j - k] + p[j] * dp[i - ][k][j]) % mod;
}
}
}
LL ans = ;
for (int i = ; i <= ; i++){
if (i > a[n]) break;
ans = (ans + dp[n][i][]) % mod;
}
return ans;
} int main(){
int t; scanf("%d", &t);
while (t--){
scanf("%s", ch);
n = strlen(ch);
bool flag = true;
for (int i = ; ch[i] != '\0'; i++){
a[i + ] = ch[i] - '';
if ((i == || i == n - ) && ch[i] > ''){
flag = false; break;
}
if (ch[i] > '') {
flag = false; break;
}
}
if (!flag) {
printf("0\n"); continue;
}
printf("%I64d\n", solve());
}
return ;
}

思路二:递推

和之前的dp类似,我们定义每次每次都只能往列上放,因此最多只能放两个。然后我们发现,如果第一个位置的地雷数确定了,后面所有的都确定了,那么我们只需要枚举一下,就有答案了

//看看会不会爆int!数组会不会少了一维!
//取物问题一定要小心先手胜利的条件
#include <bits/stdc++.h>
using namespace std;
#pragma comment(linker,"/STACK:102400000,102400000")
#define LL long long
#define ALL(a) a.begin(), a.end()
#define pb push_back
#define mk make_pair
#define fi first
#define se second
#define haha printf("haha\n")
const int maxn = 1e4 + ;
const LL mod = ;
LL dp[maxn];
char ch[maxn];
int a[maxn];
int n;
int p[] = {, , }; LL solve(){
LL ans = ;
for (int i = ; i <= && i <= a[]; i++){
if (a[] - i > ) continue;
dp[] = a[] - i;
for (int j = ; j <= n; j++){
dp[j] = a[j - ] - dp[j - ] - dp[j - ];
}
if (dp[n] + dp[n - ] != a[n]) continue;
LL res = ;
for (int j = ; j <= n; j++){
res = res * p[dp[j]];
if (res > mod) res %= mod;
}
ans = (ans + res) % mod;
}
return ans;
} int main(){
int t; cin >> t;
while (t--){
scanf("%s", ch);
n = strlen(ch);
bool flag = true;
for (int i = ; i < n; i++){
if ((i == || i == n-) && ch[i] > ''){
flag = false; break;
}
if (ch[i] > ''){
flag = false; break;
}
a[i + ] = ch[i] - '';
}
if (!flag) {
printf("0\n"); continue;
}
printf("%I64d\n", solve());
}
return ;
}