zoukankan      html  css  js  c++  java
  • 【USACO 5.5.3】Two Five

    题意

      一个5*5字符矩阵,每个字符比它左面和上面的字符都要大,它可以这样转换成一个字符串:下一行接在本行行末。所以是一个长度为25的字符串(包含A~Y的字符)。把符合条件的矩阵转换成字符串后,按字典序排序并依次编号。要求编号和字符串互相转换。

    题解

      刚开始就觉得以前做过很多类似这样的题了。但是它的限制条件相对来说比较多,也没有什么特殊规律。所以只好计数DP了。

      先看编号转字符串,枚举字符串开头(即一行一行地填字符矩阵),比如说“AB”开头的字符串有多少个?如果大于要求的编号的话,那么自然答案字符串的开头就是“AB”了。这个思想十分容易理解。

      字符串转编号,类似地!如果这个字符串是“AC~~~~~”,我们先加上"AB~~~~"的字符串个数,然后一直逼近,直至相同。

      好了。那么怎么统计以“AB”或者其他开头的字符串个数呢?

      搞个5维数组DP。每一维表示这一行填了多少个。那么F[5][5][5][5][5]=1了。此乃边界是也。

      具体看下代码,比较好理解啦。

      哦对对,算下时间复杂度先。O(55)*O(52)=O(57)=O(78125)

    代码

    /*
    TASK:twofive
    LANG:C++
    */
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    
    int f[6][6][6][6][6], code, len[5], t[5], mode, maxr[5], maxc[5];
    char cmd[2], chmat[5][5];
    bool v[25];
    
    int dp(int a, int b, int c, int d, int e, int k)
    {
        int &ans = f[a][b][c][d][e];
        if (ans) return ans;
        if (!v[k]) return dp(a, b, c, d, e, k + 1);
        if (a < 5 && k > maxr[0] && k > maxc[a]) ans += dp(a+1, b, c, d, e, k+1);
        if (b < a && k > maxr[1] && k > maxc[b]) ans += dp(a, b+1, c, d, e, k+1);
        if (c < b && k > maxr[2] && k > maxc[c]) ans += dp(a, b, c+1, d, e, k+1);
        if (d < c && k > maxr[3] && k > maxc[d]) ans += dp(a, b, c, d+1, e, k+1);
        if (e < d && k > maxr[4] && k > maxc[e]) ans += dp(a, b, c, d, e+1, k+1);
        return ans;
    }
    
    int main()
    {
        freopen("twofive.in", "r", stdin);
        freopen("twofive.out", "w", stdout);
        scanf("%s
    ", cmd);
        memset(len, 0, sizeof(len));
        code = 0;
        memset(chmat, 0, sizeof(chmat));
        if (cmd[0] == 'N') scanf("%d", &code), mode = 0;
        else
        {
            for (int i = 0; i < 5; ++i)
                for (int j = 0; j < 5; ++j)
                    scanf("%c", &chmat[i][j]);
            mode = 1;
        }
        memset(v, true, sizeof(v));
        memset(maxr, -1, sizeof(maxr));
        memset(maxc, -1, sizeof(maxc));
        for (int i = 0; i < 5; ++i)
        {
            len[i] = 0;
            for (int j = 0; j < 5; ++j)
            {
                len[i]++;
                if (mode == 0)
                {
                    for (int k = 0; k < 25; ++k)
                        if (v[k] && k > maxr[i] && k > maxc[j])
                        {
                            memset(f, 0, sizeof(f));
                            f[5][5][5][5][5] = 1;
                            v[k] = false;
                            maxr[i] = maxc[j] = k;
                            int tmp = dp(len[0], len[1], len[2], len[3], len[4], 0);
                            if (code <= tmp)
                            {
                                chmat[i][j] = 'A' + k;
                                break;
                            }
                            else
                            {
                                v[k] = true;
                                code -= tmp;
                            }
                        }
                }
                else
                {
                    for (int k = 0; k < chmat[i][j] - 'A'; ++k)
                        if (v[k] && k > maxr[i] && k > maxc[j])
                        {
                            memset(f, 0, sizeof(f));
                            f[5][5][5][5][5] = 1;
                            v[k] = false;
                            maxr[i] = maxc[j] = k;
                            code += dp(len[0], len[1], len[2], len[3], len[4], 0);
                            v[k] = true;
                        }
                    v[chmat[i][j] - 'A'] = false;
                }
            }
        }
        if (mode == 0)
        {
            for (int i = 0; i < 5; ++i)
                for (int j = 0; j < 5; ++j)
                    printf("%c", chmat[i][j]);
            printf("
    ");
        }
        else printf("%d
    ", code + 1);
        return 0;
    }
  • 相关阅读:
    *HDU 1392 计算几何
    *HDU 1115 计算几何
    *HDU 1086 计算几何
    *HDU 2108 计算几何
    HDU 1528 贪心模拟/二分图
    HDU 1281 二分图
    *HDU1150 二分图
    *HDU1151 二分图
    *HDU 1068 二分图
    *HDU 1054 二分图
  • 原文地址:https://www.cnblogs.com/albert7xie/p/5347496.html
Copyright © 2011-2022 走看看