zoukankan      html  css  js  c++  java
  • Codeforces 1117F Crisp String

    Crisp String

    显然我们只要知道每个状态合不合法我们就能解决这个问题。

    两两枚举相邻的字符, 去找不合法状态。

    #include<bits/stdc++.h>
    #define LL long long
    #define LD long double
    #define ull unsigned long long
    #define fi first
    #define se second
    #define mk make_pair
    #define PLL pair<LL, LL>
    #define PLI pair<LL, int>
    #define PII pair<int, int>
    #define SZ(x) ((int)x.size())
    #define ALL(x) (x).begin(), (x).end()
    #define fio ios::sync_with_stdio(false); cin.tie(0);
    
    using namespace std;
    
    const int N = 1e5 + 7;
    const int inf = 0x3f3f3f3f;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const int mod = 1e9 + 7;
    const double eps = 1e-8;
    const double PI = acos(-1);
    
    template<class T, class S> inline void add(T& a, S b) {a += b; if(a >= mod) a -= mod;}
    template<class T, class S> inline void sub(T& a, S b) {a -= b; if(a < 0) a += mod;}
    template<class T, class S> inline bool chkmax(T& a, S b) {return a < b ? a = b, true : false;}
    template<class T, class S> inline bool chkmin(T& a, S b) {return a > b ? a = b, true : false;}
    
    bitset<1 << 17> can[17][17];
    char s[N];
    int n, p, ans = inf, c[1 << 17];
    vector<int> pos[17], vc;
    vector<int> to[1 << 17];
    
    bool G[17][17];
    bool ok[1 << 17];
    bool vis[1 << 17];
    
    struct ST {
        int Log[N], dp[N][20];
        void build(char *s, int n) {
            Log[1] = 0;
            for(int i = 2; i <= n; i++) Log[i] = Log[i >> 1] + 1;
            for(int i = 1; i <= n; i++) dp[i][0] = 1 << (s[i] - 'a');
            for(int j = 1; j <= Log[n]; j++)
                for(int i = 1; i <= n; i++)
                    dp[i][j] = dp[i][j - 1] | dp[i + (1 << (j - 1))][j - 1];
        }
        inline int query(int L, int R) {
            if(L > R) return 0;
            int k = Log[R - L + 1];
            return dp[L][k] | dp[R - (1 << k) + 1][k];
        }
    } rmqOr;
    
    int main() {
        scanf("%d%d", &n, &p);
        scanf("%s", s + 1);
        for(int i = 0; i < p; i++)
            for(int j = 0; j < p; j++)
                scanf("%d", &G[i][j]);
    
        for(int i = 0; i < (1 << p); i++) {
            ok[i] = true;
            for(int j = 0; j < p; j++) {
                if(i >> j & 1) continue;
                to[i].push_back(j);
            }
        }
    
        rmqOr.build(s, n);
    
    
        for(int i = 1; i <= n; i++) pos[s[i] - 'a'].push_back(i);
    
        for(int i = 1; i < (1 << p); i++)
            for(int j = 0; j < p; j++)
                if(i >> j & 1) c[i] += SZ(pos[j]);
    
        for(int i = 0; i < p; i++) {
            for(int j = 0; j < p; j++) {
                if(G[i][j]) continue;
                if(i == j) {
                    for(int k = 1; k < SZ(pos[i]); k++)
                        can[i][j][rmqOr.query(pos[i][k - 1] + 1, pos[i][k] - 1)] = true;
                } else {
                    vc.resize(SZ(pos[i]) + SZ(pos[j]));
                    merge(ALL(pos[i]), ALL(pos[j]), vc.begin());
                    for(int k = 1; k < SZ(vc); k++) {
                        if(s[vc[k]] != s[vc[k - 1]]) {
                            can[i][j][rmqOr.query(vc[k - 1] + 1, vc[k] - 1)] = true;
                        }
                    }
                }
                for(int mask = 0; mask < (1 << p); mask++) {
                    if(!can[i][j][mask]) continue;
                    for(auto& k : to[mask]) can[i][j][mask | (1 << k)] = true;
                }
            }
        }
    
        for(int mask = 0; mask < (1 << p); mask++) {
            int fmask = mask ^ ((1 << p) - 1);
            for(int i = 0; i < p && ok[mask]; i++) {
                if(mask >> i & 1) {
                    for(int j = i; j < p && ok[mask]; j++) {
                        if(mask >> j & 1) {
                            if(can[i][j][fmask]) ok[mask] = false;
                        }
                    }
                }
            }
        }
        
        vis[(1 << p) - 1] = true;
        queue<int> que;
        que.push((1 << p) - 1);
        while(!que.empty()) {
            int mask = que.front();
            que.pop();
            chkmin(ans, c[mask]);
            for(int i = 0; i < p; i++) {
                if(mask >> i & 1 && !vis[mask ^ (1 << i)] && ok[mask ^ (1 << i)]) {
                    vis[mask ^ (1 << i)] = true;
                    que.push(mask ^ (1 << i));
                }
            }
        }
        printf("%d
    ", ans);
        return 0;
    }
    
    /*
    */
  • 相关阅读:
    mysqlEasyHelper(待完善)
    入门day2
    入门day1
    c# 多态的理解
    c# 简单任务控制
    c# 陌生的关键字
    从0来搭建超灵活的MVP商用框架<三>-------网络层加入RxJava、事件总线封装、Dagger2集成
    从0来搭建超灵活的MVP商用框架<二>-------APP基础配置、Okhttp+Retrofit封装
    从0来搭建超灵活的MVP商用框架<一>-------从MVC至MVP的转变、通用网络切换框架
    IOC注入框架设计<三>-------Android Studio插件开发来自动生成ButterKnife相关代码
  • 原文地址:https://www.cnblogs.com/CJLHY/p/10938441.html
Copyright © 2011-2022 走看看