zoukankan      html  css  js  c++  java
  • Task On The Board(构造、贪心)

    题意

    给定一个由小写字母构成的字符串(s),从中选取(m)个字符构成一个新的字符串(t)(字符可乱序),满足一个序列(b)

    序列(b)的定义如下:

    (b_i = sum_{t_j > t_i}|j - i|, 1 leq i, j leq |t|)

    数据范围

    (1 leq T leq 100)

    (1 leq |s| leq 50)

    (1 leq m leq |s|)

    (0 leq b_i leq 1225)

    思路

    考察(b_i = 0)的位置。满足(b_i = 0)的字符意味着在(t)中,没有比其更大的字符。

    因此,我们可以从大到小遍历所有字符,若当前字符的个数不少于(b_i = 0)的个数,那么这些位置就可以用这个字符填充。

    因为填充的这些字符一定比其他位置上的字符大,因此可以更新其他位置的(b_j),即(b_j = b_j - |i - j|)

    然后再找(b_j = 0)的位置,并从从大到小遍历比当前已填充字符小的字符,后面操作同上,直到填充完毕。

    数据保证一定有解,那么这种构造方法一定是对的。

    反证法证明,若不找最大字符填充,而是找另外的字符填充。我们考察下一步可选字符的集合,前者设为(A),后者设为(B)

    由于(B)(A)的子集,因此,若用最大字符填充的方法不对,那么其他填充方法也不对,故原贪心策略正确。

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <unordered_map>
    
    using namespace std;
    
    const int N = 55;
    
    int n;
    char s[N], ans[N];
    int b[N];
    int is_cur[N];
    
    int main()
    {
        int T;
        scanf("%d", &T);
        while(T --) {
            scanf("%s", s + 1);
            scanf("%d", &n);
            for(int i = 1; i <= n; i ++) scanf("%d", &b[i]);
            memset(ans, '', sizeof(ans));
            memset(is_cur, 0, sizeof(is_cur));
            unordered_map<char, int> mp;
            int len = strlen(s + 1);
            for(int i = 1; i <= len; i ++) {
                mp[s[i]] ++;
            }
            int cnt = 0;
            int loc = 25;
            while(cnt < n) {
                int num = 0;
                for(int i = 1; i <= n; i ++) {
                    if(!b[i]) {
                        num ++;
                        is_cur[i] = 1;
                    }
                }
                char ch;
                for(int i = loc; i >= 0; i --) {
                    char tmp = i + 'a';
                    if(mp[tmp] >= num) {
                        ch = tmp;
                        loc = i - 1;
                        break;
                    }
                }
                for(int i = 1; i <= n; i ++) {
                    if(!b[i] && is_cur[i] == 1) {
                        b[i] = -1;
                        is_cur[i] = -1;
                        ans[i] = ch;
                        cnt ++;
                        for(int j = 1; j <= n; j ++) {
                            if(b[j]) {
                                b[j] -= abs(i - j);
                            }
                        }
                    }
                }
            }
            printf("%s
    ", ans + 1);
        }
        return 0;
    }
    
  • 相关阅读:
    Can't remove netstandard folder from output path (.net standard)
    website项目的reference问题
    The type exists in both DLLs
    git常用配置
    Map dependencies with code maps
    How to check HTML version of any website
    Bootstrap UI 编辑器
    网上职位要求对照
    Use of implicitly declared global variable
    ResolveUrl in external JavaScript file in asp.net project
  • 原文地址:https://www.cnblogs.com/miraclepbc/p/14381927.html
Copyright © 2011-2022 走看看