zoukankan      html  css  js  c++  java
  • CF

    题目传送门

    题解:

    枚举非法对。

      如果 ‘a'  和 ’b' 不能相邻的话,那么删除 'a' 'b'之间的字符就是非法操作了。 假设题目给定的字符串为 "acdbe",所以删除cd是非法操作, 因为cd是非法了,所以cde也是非法操作,

        也就是说找到所有的非法操作之后往外推,比他多删的状态就一样是非法的了,当然对于上述的“acdbe"来说,不能确定 ”acd"是非法操作,因为在枚举非法对的时候,该非法对的字符并不能被删除。

    然后把所有非法对的非法状态都存下来。然后从没删除的状态往外搜,就好了。

    代码:

    /*
    code by: zstu wxk
    time: 2019/03/06
    Problem Link: http://codeforces.com/contest/1117/problem/F
    Solve:
    */
    #include<bits/stdc++.h>
    using namespace std;
    #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
    #define LL long long
    #define ULL unsigned LL
    #define fi first
    #define se second
    #define pb push_back
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define lch(x) tr[x].son[0]
    #define rch(x) tr[x].son[1]
    #define max3(a,b,c) max(a,max(b,c))
    #define min3(a,b,c) min(a,min(b,c))
    typedef pair<int,int> pll;
    const int inf = 0x3f3f3f3f;
    const int _inf = 0xc0c0c0c0;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const LL _INF = 0xc0c0c0c0c0c0c0c0;
    const LL mod =  (int)1e9+7;
    const int N = 1e5 + 100;
    char s[N];
    int a[20][20], cnt[20];
    int tmp[1<<18], gg[1<<18];
    int n, m, k;
    void solve(int u, int v){
        memset(tmp, 0, sizeof(tmp));
        for(int i = 1, j; i <= n;){
            while(i <= n && s[i]-'a' != u) ++i;
            int t = 0;
            j = i+1;
            while(j <= n && s[j] -'a' != u && s[j]-'a' !=  v) {
                t |= 1 << s[j]-'a';
                ++j;
            }
            if(j > n) break;
            if(s[j] - 'a' == v){
                i = j+1;
                tmp[t] = 1;
            }
            if(s[j] - 'a' == u)
                i = j;
        }
        for(int i = 0; i <= k; ++i){
            if(tmp[i]){
                gg[i] = 1;
                for(int j = 0; j < m; ++j){
                    if(j == u || j == v) continue;
                    tmp[i|(1<<j)] = 1;
                }
            }
        }
        return ;
    }
    int vis[1<<18];
    int ans;
    void DFS(int x, int len){
        if(vis[x]) return ;
        vis[x] = 1;
        ans = min(ans, len);
        for(int i = 0; i < m; ++i){
            if(gg[x | (1<<i)]) continue;
            DFS(x|1<<i, len-cnt[i]);
        }
        return ;
    }
    
    void Ac(){
        memset(gg, 0, sizeof(gg));
        memset(cnt, 0, sizeof cnt);
        scanf("%s", s+1);
        for(int i = 0; i < m; ++i)
            for(int j = 0; j < m; ++j)
                scanf("%d", &a[i][j]);
        k = (1<<m) - 1;
        for(int i = 0; i < m; ++i)
            for(int j = 0; j < m; ++j)
                if(a[i][j] == 0)
                    solve(i,j);
        for(int i = 1; i <= n; ++i){
            cnt[s[i]-'a']++;
        }
        ans = n;
        DFS(0, n);
        printf("%d
    ", ans);
        return ;
    }
    int main(){
        while(~scanf("%d%d", &n, &m)){
            Ac();
        }
        return 0;
    }
    View Code

      

  • 相关阅读:
    Android ListView的使用(三)
    Android GridView的使用页面按钮
    Android ListView的使用(二)
    Android ListView的使用(一)
    Linux 下MongoDb的安装
    Linux使用redis
    JavaWeb之JDBC
    JavaWeb之多语言国际化
    JavaWeb之JSTL标签
    JavaWeb之JSP技术总结
  • 原文地址:https://www.cnblogs.com/MingSD/p/10496334.html
Copyright © 2011-2022 走看看