[BZOJ1394][[Baltic2005]ancient]

[Baltic2005]ancient

Description

波罗的海的考古学家最近正参与一个非常重要的工程,并发现了一个古老的手稿 ,这个手稿对于理解他们正在探索区域的居民文化起着关键性的作用。手稿上主要由图案构成, 因此考古学家能够对文档的主题有个大致的概念。 然而,手稿中仍有一些书写部分,使考古学家百思不得其解。由于除了其所使用语言过于古老,手稿还有部分段落被毁,其中一些单词也模糊了,所以他们不能完整的理解这部分的含义。 其中一个考古学家说,手稿中的一些单词使他想到了某种语言:在这种语言的单词中不会有超过Vc个连续的元音和Cc连续的辅音, 同时不会有超过VE个连续的元音和CE个连续的辅音是相同的。 考古学家留下一组人员寻找更多准确的信息。另一部分人, 在等待那些人的回音的同时,决定检查手稿中是否有东西违背那位考古学家的假设,并且估计目前的工作量,所以他们想知道手稿究竟有多少种译解方法。我们必须帮助他们! 注意: 元音是指 “aeiou” 而其它21个英文字母为辅音。
Input
The first line of the input file contains four integers VE, VC, CE and CC (1 ≤ VE ≤ VC ≤ 4, 1 ≤ CE ≤ CC ≤ 4) separated by single spaces. 第二行描述一个从手稿中抽出的单词,它由最多15个英文小写单词构成,如果某一位为“*”,那么说明这个字母已经模糊不清了。
Output
输出只有一个整数,描述有多少种可能的合法单词符合上文给出的限制条件。你可以假设答案不超过64位带符号的整数。有可能那位考古学家的假设是错误的,不存在任何一种可能的合法单词,那么答案输出为0。
Sample Input
1 1 1 1
a**
Sample Output
105

Solution
裸dp
dp[i][0/1][cnt1][cnt2][nowch]
第i位,元/辅音,同类连续个数,相同字母连续个数,最后一位字母
随意转移

Code

#include <bits/stdc++.h>
using namespace std;

#define rep(i, l, r) for (int i = (l); i <= (r); i++)
#define per(i, r, l) for (int i = (r); i >= (l); i--)
#define MS(_) memset(_, 0, sizeof(_))
#define MP make_pair
#define PB push_back
#define hash _hash
typedef long long ll;
typedef pair<int, int> PII;
template<typename T> inline void read(T &x){
    x = 0; T f = 1; char ch = getchar();
    while (!isdigit(ch)) {if (ch == '-') f = -1; ch = getchar();}
    while (isdigit(ch))  {x = x * 10 + ch - '0'; ch = getchar();}
    x *= f;
}
inline void setIO(){
    freopen("ancient.in", "r", stdin);
    freopen("ancient.out", "w", stdout);
}

map<char, int> hash;
int C[2], E[2], l;
char st[20];
ll f[20][2][10][10][200];

int main(){
    //setIO();

    read(E[1]); read(C[1]); read(E[0]); read(C[0]);
    scanf("%s", st+1); l = strlen(st + 1);

    hash['a'] = hash['e'] = hash['i'] = hash['o'] = hash['u'] = 1;

    if (st[1] == '*'){
        rep(nowch, 'a', 'z') f[1][hash[nowch]][1][1][nowch] = 1;   
    }else f[1][hash[st[1]]][1][1][st[1]] = 1;

    rep(i, 2, l) rep(nowch, 'a', 'z')
        if ((st[i] == '*') || (nowch == st[i])) { int p = hash[nowch];
            rep(lastch, 'a', 'z') 
                if ((st[i-1] == '*') || (lastch == st[i-1])){ int q = hash[lastch];
                    if (p == q){
                        if (nowch == lastch){
                            rep(c, 2, C[p]) rep(e, 2, E[p])
                                f[i][p][c][e][nowch] += f[i-1][p][c-1][e-1][lastch];        
                        }else{
                            rep(c, 2, C[p]) rep(laste, 1, E[p])
                                f[i][p][c][1][nowch] += f[i-1][p][c-1][laste][lastch];
                        }
                    }else{
                        rep(lastc, 1, C[q]) rep(laste, 1, E[q])
                            f[i][p][1][1][nowch] += f[i-1][q][lastc][laste][lastch];
                    }
                }
        }

    ll ans = 0;
    rep(nowch, 'a', 'z') if ((st[l] == '*') || (nowch == st[l])) { int p = hash[nowch];
        rep(c, 1, C[p]) rep(e, 1, E[p]) ans += f[l][p][c][e][nowch];
    }
    printf("%llu\n", ans);

    return 0;
}

你可能感兴趣的:(动态规划)