Consonant Fencity Gym - 101612C(压状+暴力)

题目大意

输入一串仅含有小写字母的字符串, 让某些辅音字母变成大写(一个变大写同种辅音都变大写)。输出使得相邻辅音大小写不同的个数最多的字符串。

思路

枚举所有辅音大小写的变化组合,最多2^19,然后选出最优的状态。本题的重点是怎样保存这个状态,可以用二进制来保存,对于每种状态通过枚举两个辅音字母来统计相邻个数,然后维护一个最优状态。

代码

#include <bits/stdc++.h>
using namespace std;
const int maxn = (int)1e6 + 10, inf = 0x3f3f3f3f;

char s[maxn];
int n;                      
int ans, cnt, ansolve;
int cons[30];      // 记录该字符串出现的辅音字母
int mm[30];       // 辅音字母  在一个状态中所处的二进制位置,方便输出答案
int mp[30][30]; 

int idx(char c) {
    return c - 'a';
}

bool judge(char c) {
    if(c=='a'||c=='e'||c=='i'||c=='o'||c=='u'||c=='w'||c=='y') {
        return false;
    }
    else return true;
}

void init() {
    n = (int)strlen(s);
    memset(mp, 0, sizeof(mp));
    cnt = 0;
    int vis[30];
    memset(vis, 0, sizeof(vis));
    if(judge(s[0])) {
        vis[idx(s[0])] = 1;
        cons[cnt++] = idx(s[0]);
        mm[idx(s[0])] = 1;
    }
    for(int i = 1; i < n; i++) {
        if(judge(s[i])&&!vis[idx(s[i])]) {
            vis[idx(s[i])] = 1;
            mm[idx(s[i])] = 1<<cnt;
            cons[cnt++] = idx(s[i]);
        }
        if(judge(s[i-1])&&judge(s[i])) {
            mp[idx(s[i-1])][idx(s[i])]++;
        }
    }
}

void solve() {
    int m = 1 << cnt;
    for (int zt = 1; zt < m; zt++) {
        int sum = 0;
        for (int i = 0; i < cnt; i++) {
            for (int j = i + 1; j < cnt; j++) {
                if (((zt & 1 << i) || (zt & 1 << j)) && !((zt & 1 << i) && (zt & 1 << j))) {
                    sum += mp[cons[i]][cons[j]];
                    sum += mp[cons[j]][cons[i]];
                }
            }
            if (ans < sum) {
                ans = sum;
                ansolve = zt;
            }
        }
    }
    //cout << ans << endl;
    for (int i = 0; i < n; i++) {
        if (judge(s[i]) && mm[idx(s[i])]&ansolve) {
            printf("%c", toupper(s[i]));
        } else {
            printf("%c", s[i]);
        }
    }
    cout << endl;
}

int main() {
    //freopen("input.txt", "r", stdin);
    freopen("consonant.in", "r", stdin);
    freopen("consonant.out", "w", stdout);
    while(~scanf("%s", s)) {
        init();
        solve();
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值