作者 imtian
单位 临沂大学
给定一个只包含下划线和大写字母的字符串,将下划线全部换成大写字母,问有多少种填法能使这个字符串满足以下三种要求:
- 不包含三个及以上连续的元音字母;
- 不包含三个及以上连续的辅音字母;
- 至少包含一个大写字母 L。
元音字母仅包含A,E,I,O,U,其他的字母都是辅音字母。
输入格式:
输入的一行给出一行字符串S;
∣S∣≤100
题目保证最多含有10个下划线,并且只会出现大写字母和下划线。
输出格式:
输出一个整数——表示方案数。
输入样例:
L_V
输出样例:
5
输入样例:
JA_BU_K_A
输出样例:
485
思路:
把字符分成三类:L,元音字符,除L的辅音字符。
先填满再判断是否正确。
方法:
用dfs填满下划线。
void dfs(ll x){//x为下标 if(x == wz.size()){//填满了 ll cnt=1; for(ll i = 0 ; i < wz.size() ; i ++)cnt*=v[i]; if(pd())sum+=cnt;//只有方案可行才加 return; } for(ll j = 0 ; j < 3 ; j ++){//往后填 str[wz[x]]=tian[j]; if(j == 0)v[x]=1; else if(j == 1)v[x]=5; else v[x]=20; dfs(x+1); } }
判断这个取法正不正确。
bool pd(){//判断字符串是否满足条件 bool f=1,l=0;//初始:没三个连续,没L字母 for(ll i = 0 ; i < str.size() ; i ++){ if(str[i] == 'L')l=1;//有L字母则更新 //元音字母vis[i]=true,辅音 vis[i]=false F.find(str[i]) != -1 ? vis[i]=1 : vis[i]=0; if(i < 2)continue; //判断是否有三个连续的同类型字母 if(vis[i] == vis[i-1] && vis[i] == vis[i-2])f=0; } return f&&l; }
AC代码:
#include<bits/stdc++.h> using namespace std; typedef long long ll; #define endl "\n" const ll N = 1e2 + 7; //字符串,填充的各个类型的字符,元音字符 string str,tian="LAB",F="AEIOU"; vector<ll>wz;//下划线的位置 ll v[N],sum=0; bool vis[N];//标记此位置是否为元音字符 bool pd(){//判断字符串是否满足条件 bool f=1,l=0;//初始:没三个连续,没L字母 for(ll i = 0 ; i < str.size() ; i ++){ if(str[i] == 'L')l=1;//有L字母则更新 //元音字母vis[i]=true,辅音 vis[i]=false F.find(str[i]) != -1 ? vis[i]=1 : vis[i]=0; if(i < 2)continue; //判断是否有三个连续的同类型字母 if(vis[i] == vis[i-1] && vis[i] == vis[i-2])f=0; } return f&&l; } void dfs(ll x){//x为下标 if(x == wz.size()){//填满了 ll cnt=1; for(ll i = 0 ; i < wz.size() ; i ++)cnt*=v[i]; if(pd())sum+=cnt;//只有方案可行才加 return; } for(ll j = 0 ; j < 3 ; j ++){//往后填 str[wz[x]]=tian[j]; if(j == 0)v[x]=1; else if(j == 1)v[x]=5; else v[x]=20; dfs(x+1); } } void solve(){ cin >> str; for(ll i = 0 ; i < str.size() ; i ++) if(str[i] == '_')wz.push_back(i); dfs(0); cout << sum << endl; return; } int main(){ ll t=1;//cin >> t; while(t --)solve(); return 0; }