P7541 [COCI2009-2010#1] DOBRA 题解

题目传送门

错误思路

暴力搜,搜每个下划线位置的字母,记下划线个数为 $m$,则 $m\le10$,时间复杂度 $O(26^m)$,超时。

正解

思路

很容易想到其实 $5$ 个元音字母没有本质区别,除了 $\texttt{L}$ 外的辅音字母也一样。我们在搜时只需要在下划线处搜:

  1. 元音字母
  2. 除 $\texttt{L}$ 外的辅音字母
  3. $\texttt{L}$

三个情况即可。

需要注意的是: 由于搜元音时,我们可以在下划线处填任意元音字母,所以填元音字母的方案数要乘以 $5$。同理,搜除 $\texttt{L}$ 外的辅音字母时要乘以 $26-5-1=20$。$\texttt{L}$ 就不需要了,因为只可能填 $\texttt{L}$。

代码

#include <iostream>
using namespace std;

string s;
#define isyy(c) (c=='A'||c=='E'||c=='I'||c=='O'||c=='U')//判断是否是元音
long long dfs(int dep,int y,int f,bool L)//y:连续元音个数,f:连续辅音个数,L:当前是否有‘L’
{
    if(y>=3||f>=3)
    {
        return 0;
    }
    if(s.size()<=dep)
    {
        return (long long)L;//有‘L’才“令人愉快”
    }
    long long t=0;
    if(s[dep]=='_')
    {
        //填元音字母
        s[dep]='A';//用‘A’代表元音
        t+=5*dfs(dep+1,y+1/* 连续元音数量加1 */,0/* 连续辅音数量清0。下同。 */,L);//一共可填5种元音
        //填辅音字母
        s[dep]='B';//用‘B’代表辅音
        t+=20*dfs(dep+1,0,f+1,L);//‘L’特殊考虑,26-5-1=20,一共可填20种辅音
        //填‘L’
        s[dep]='L';
        t+=dfs(dep+1,0,f+1,true);
        s[dep]='_';//恢复原状
        return t;
    }
    else//如果不是下划线
    {
        if(isyy(s[dep]))
        {
            return dfs(dep+1,y+1,0,L);
        }
        else
        {
            if(s[dep]=='L')
            {
                return dfs(dep+1,0,f+1,true);
            }
            else
            {
                return dfs(dep+1,0,f+1,L);
            }
        }
    }
}

int main()
{
    cin>>s;
    printf("%lld",dfs(0,0,0,false));
    return 0;
}

注意

你需要使用 $64$ 位有符号整数。在 C/C++ 中使用 long long,Pascal 中使用 int64。 ——题面

posted @ 2023-07-03 14:26  Po7ed  阅读(9)  评论(0编辑  收藏  举报  来源