HDU 5965 三维dp 或 递推
题意:= =中文题
思路一:比赛时队友想的。。。然后我赛后想了一下想了个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 = 100000007; const int maxn = 1e4 + 5; LL dp[maxn][3][6]; char ch[maxn]; int a[maxn]; int n; LL p[3] = {1, 2, 1}; LL solve(){ memset(dp, 0, sizeof(dp)); for (int i = 0; i <= 2; i++) { if (a[1] - i > 2) continue; if (a[1] - i < 0) break; dp[1][i][a[1] - i] = p[i]; } for (int i = 2; i <= n; i++){ for (int j = 0; j <= 2; j++){ for (int k = 0; k <= 2; k++){ if (a[i] - j - k > 2) continue; if (a[i] - j - k < 0) break;///目前放入j个,dp[i-1]剩下j个 dp[i][j][a[i] - j - k] = (dp[i][j][a[i] - j - k] + p[j] * dp[i - 1][k][j]) % mod; } } } LL ans = 0; for (int i = 0; i <= 2; i++){ if (i > a[n]) break; ans = (ans + dp[n][i][0]) % mod; } return ans; } int main(){ int t; scanf("%d", &t); while (t--){ scanf("%s", ch); n = strlen(ch); bool flag = true; for (int i = 0; ch[i] != '\0'; i++){ a[i + 1] = ch[i] - '0'; if ((i == 0 || i == n - 1) && ch[i] > '4'){ flag = false; break; } if (ch[i] > '6') { flag = false; break; } } if (!flag) { printf("0\n"); continue; } printf("%I64d\n", solve()); } return 0; }
思路二:递推
和之前的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 + 5; const LL mod = 100000007; LL dp[maxn]; char ch[maxn]; int a[maxn]; int n; int p[3] = {1, 2, 1}; LL solve(){ LL ans = 0; for (int i = 0; i <= 2 && i <= a[1]; i++){ if (a[1] - i > 2) continue; dp[1] = a[1] - i; for (int j = 2; j <= n; j++){ dp[j] = a[j - 1] - dp[j - 1] - dp[j - 2]; } if (dp[n] + dp[n - 1] != a[n]) continue; LL res = 1; for (int j = 1; 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 = 0; i < n; i++){ if ((i == 0 || i == n-1) && ch[i] > '4'){ flag = false; break; } if (ch[i] > '6'){ flag = false; break; } a[i + 1] = ch[i] - '0'; } if (!flag) { printf("0\n"); continue; } printf("%I64d\n", solve()); } return 0; }