zoukankan      html  css  js  c++  java
  • Codeforces 814E An unavoidable detour for home dp

    An unavoidable detour for home

    首先明确的一点是从前往后dp, 因为有dis[ i + 1 ] >= dis[ i ] 这个条件存在。

    然后我先就考虑将顶点一个一个填进去, 但是发现需要开六七个50乘起来的数组才能维护。

    我发现有一个条件还没有利用起来, 就是每个点到 1 的最短路唯一, 我们考虑将到 1 距离一样的点

    一起考虑去更新dp。

    dp[ o ][ i ][ j ] 表示处理到完了o, 还有 i 个顶点需要 1 的度数, 还有 j 个顶点需要 2 的度数。

    对于dp[ o ][ i ][ j ] 需要i + 2 * j 个当前这个段连接才能转移。

    way1[ i ][ j ] 表示有 i 个顶点需要 1 的度数, 有 j 个顶点需要 2 的度数, 填满这样的段的方案数。

    way2[ l ][ r ][ i ][ j ] 表示考虑l - r作为一个整体的一段, 每个都向之前一段连条边,

    段内相互连边之后有 i 个顶点需要 1 的度数, 有 j 个顶点需要 2 的度数的方案数。

    然后就可以转移啦。 有点恶心就是了。 

    #include<bits/stdc++.h>
    #define LL long long
    #define LD long double
    #define ull unsigned long long
    #define fi first
    #define se second
    #define mk make_pair
    #define PLL pair<LL, LL>
    #define PLI pair<LL, int>
    #define PII pair<int, int>
    #define SZ(x) ((int)x.size())
    #define ALL(x) (x).begin(), (x).end()
    #define fio ios::sync_with_stdio(false); cin.tie(0);
    
    using namespace std;
    
    const int N = 51;
    const int inf = 0x3f3f3f3f;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const int mod = 1e9 + 7;
    const double eps = 1e-8;
    const double PI = acos(-1);
    
    template<class T, class S> inline void add(T& a, S b) {a += b; if(a >= mod) a -= mod;}
    template<class T, class S> inline void sub(T& a, S b) {a -= b; if(a < 0) a += mod;}
    template<class T, class S> inline bool chkmax(T& a, S b) {return a < b ? a = b, true : false;}
    template<class T, class S> inline bool chkmin(T& a, S b) {return a > b ? a = b, true : false;}
    
    int n, d[N];
    int way1[N][N];
    int way2[N][N][N][N];
    int dp[N][N][N];
    
    int main() {
        scanf("%d", &n);
        for(int i = 1; i <= n; i++) scanf("%d", &d[i]);
        for(int i = 0; i <= n; i++) {
            for(int j = 0; j <= n; j++) {
                int ret = 1, tot = i + 2 * j, num1 = i, num2 = j;
                while(num2--) ret = 1LL * tot * (tot - 1) / 2 * ret % mod, tot -= 2;
                while(num1--) ret = 1LL * ret * tot % mod, tot--;
                way1[i][j] = ret;
            }
        }
        for(int l = 1; l <= n; l++) {
            for(int r = l; r <= n; r++) {
                int len = r - l + 1;
                for(int i = l; i <= r; i++) {
                    for(int j = 0; j <= len; j++) {
                        for(int k = 0; j + k <= len; k++) {
                            dp[i][j][k] = 0;
                        }
                    }
                }
                if(d[l] == 2) dp[l][1][0] = 1;
                else dp[l][0][1] = 1;
                for(int o = l; o < r; o++) {
                    for(int i = 0; i <= len; i++) {
                        for(int j = 0; i + j <= len; j++) {
                            if(!dp[o][i][j]) continue;
                            if(d[o + 1] == 2) {
    
                                add(dp[o + 1][i + 1][j], dp[o][i][j]);
    
                                if(i) add(dp[o + 1][i - 1][j], 1LL * dp[o][i][j] * i % mod);
                                if(j) add(dp[o + 1][i + 1][j - 1], 1LL * dp[o][i][j] * j % mod);
                            } else {
                                add(dp[o + 1][i][j + 1], dp[o][i][j]);
    
    
                                if(i) add(dp[o + 1][i][j], 1LL * dp[o][i][j] * i % mod);
                                if(j) add(dp[o + 1][i + 2][j - 1], 1LL * dp[o][i][j] * j % mod);
    
                                if(i >= 2) add(dp[o + 1][i - 2][j], 1LL * dp[o][i][j] * (i * (i - 1) / 2) % mod);
                                if(j >= 2) add(dp[o + 1][i + 2][j - 2], 1LL * dp[o][i][j] * (j * (j - 1) / 2) % mod);
                                if(i && j) add(dp[o + 1][i][j - 1], 1LL * dp[o][i][j] * (i * j) % mod);
                            }
                        }
                    }
                }
                for(int i = 0; i <= len; i++) {
                    for(int j = 0; i + j <= len; j++) {
                        way2[l][r][i][j] = dp[r][i][j];
                    }
                }
            }
        }
        memset(dp, 0, sizeof(dp));
        if(d[1] == 2) {
            for(int i = 0; i <= 2; i++) {
                for(int j = 0; i + j <= 2; j++) {
                    add(dp[3][i][j], way2[2][3][i][j]);
                }
            }
        } else {
            for(int i = 0; i <= 3; i++) {
                for(int j = 0; i + j <= 3; j++) {
                    add(dp[4][i][j], way2[2][4][i][j]);
                }
            }
        }
        for(int o = 3; o < n; o++) {
            for(int i = 0; i <= o; i++) {
                for(int j = 0; i + j <= o; j++) {
                    if(!dp[o][i][j]) continue;
                    if(!i && !j) continue;
                    int len = i + 2 * j, l = o + 1, r = o + len;
                    if(o > n) continue;
                    for(int u = 0; u <= len; u++) {
                        for(int v = 0; u + v <= len; v++) {
                            add(dp[r][u][v], 1LL * way2[l][r][u][v] * way1[i][j] % mod * dp[o][i][j] % mod);
                        }
                    }
                }
            }
        }
        printf("%d
    ", dp[n][0][0]);
        return 0;
    }
    
    /*
    */
  • 相关阅读:
    用BAT执行python文件
    python写MD5翻译器
    python操作数据库
    百度哪些事
    Python基础教程笔记——使用字符串
    python操作webservices
    Export to Microsoft Excel On a Dynamics AX Form With Multiple Data Sources【转】
    ログインユーザーの権限をJavaScriptでチェックする
    使用JSOM检查文件或文件夹是否存在
    在SharePoint 2013 Wiki Page中使用用户选择对话框
  • 原文地址:https://www.cnblogs.com/CJLHY/p/11091234.html
Copyright © 2011-2022 走看看