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

      

  • 相关阅读:
    LeetCode 295. Find Median from Data Stream (堆)
    LeetCode 292. Nim Game(博弈论)
    《JavaScript 模式》读书笔记(4)— 函数2
    《JavaScript 模式》读书笔记(4)— 函数1
    《JavaScript 模式》读书笔记(3)— 字面量和构造函数3
    《JavaScript 模式》读书笔记(3)— 字面量和构造函数2
    《JavaScript 模式》读书笔记(3)— 字面量和构造函数1
    《JavaScript 模式》读书笔记(2)— 基本技巧3
    《JavaScript 模式》读书笔记(2)— 基本技巧2
    《JavaScript 模式》读书笔记(2)— 基本技巧1
  • 原文地址:https://www.cnblogs.com/MingSD/p/10496334.html
Copyright © 2011-2022 走看看