zoukankan      html  css  js  c++  java
  • 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
    ")
    /*
    定义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] != ''; 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
    "); continue;
            }
            printf("%I64d
    ", solve());
        }
        return 0;
    }
    View Code

    思路二:递推

    和之前的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
    ")
    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
    "); continue;
            }
            printf("%I64d
    ", solve());
        }
        return 0;
    }
    View Code
  • 相关阅读:
    eclipse中的项目的JRE换成JDK
    Eclipse中maven项目的创建和运行
    git 发布命令
    vbox中虚拟ubuntu增加新的虚拟硬盘
    MyServer
    java常用的中间件
    高并发解决方案
    浅谈SpringMVC
    浅谈HIbernate
    javaweb笔记七
  • 原文地址:https://www.cnblogs.com/heimao5027/p/6033812.html
Copyright © 2011-2022 走看看