zoukankan      html  css  js  c++  java
  • hdu 3183

    Problem Description
    Kiki likes traveling. One day she finds a magic lamp, unfortunately the genie in the lamp is not so kind. Kiki must answer a question, and then the genie will realize one of her dreams.
    The question is: give you an integer, you are allowed to delete exactly m digits. The left digits will form a new integer. You should make it minimum.
    You are not allowed to change the order of the digits. Now can you help Kiki to realize her dream?
     

    Input
    There are several test cases. Each test case will contain an integer you are given (which may at most contains 1000 digits.) and the integer m (if the integer contains n digits, m will not bigger then n). The given integer will not contain leading zero.
     

    Output
    For each case, output the minimum result you can get in one line. If the result contains leading zero, ignore it.
     

    Sample Input

    178543 4
    1000001 1
    100001 2
    12345 2
    54321 2

     

    Sample Output

    13
    1
    0
    123
    321
    题意:给出一个没有前导0的字符串  求删除k个数后最小的数

    分析: 首先判断0的个数 如果有0 看0之前的非0数是否比k大 如果不比k大 优先考虑去除这些字符 循环此操作直到 0之前的非0数比k大或者没有0为止

    如果字符串中的非0数不比 k 大 输出0   然后就是判断顺序递增与不递增的情况  递增的话就是去掉后面几位  非递增的话就是去掉前面的逆序数

    #include<cstdio>
    #include<cstring>
    #include<stack>
    #include<vector>
    #include<queue>
    #include<cmath>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int oo = 0x3f3f3f3f;
    const int maxn = 1e6+7;
    const int mod = 1e9+7;
    typedef long long LL;
    char str[20000], s[20000];
    int vis[30], sign[20000];
    int main()
    {
        int i, m, k, j, a, id, cnt, last, g;
        ///last 去除0之前的数后现在的位置 g有多少个非0数
        while(scanf("%s %d", str, &m)!=EOF)
        {
            g = 0;
            memset(vis, 0, sizeof(vis));///标记字符串中数字的次数
            memset(sign, 0, sizeof(sign));///标记该位置的字符是否被去除
            for(i = 0; str[i] != ''; i++)
            {
                vis[str[i]-'0']++;
                if(str[i] != '0') g++;
            }
    
            int len = strlen(str);last = 0;
            if(m == len || g <= m)
            {
                printf("0
    ");
                continue;
            }
            if(vis[0] > 0)
            {
                while(1)///循环去除0之前所有能去除的数字以及0
                {
                    cnt = 0;
                    for(i = last; i < len; i++)
                    {
                        if(str[i] == '0')
                        {
                            id = i;
                            break;
                        }
                        cnt++;
                    }
                    if(cnt > m) break;
                    for(i = last; i < id; i++)
                        vis[str[i]-'0']--;
                    m -= cnt;
                    while(str[id] == '0' && id < len)
                    {
                        vis[0] --;
                        id++;
                    }
                    last = id;
                    if(id == len || vis[0] == 0) break;
                }
            }
            ///去除非递增序列的数(逆序数)
            for(i = last; i < len; i++) 
            {
                for(j = i-1; j >= last; j--)
                {
                    if(str[j] > str[i] && sign[j] == 0)
                    {
                        sign[j] = 1;
                        vis[str[j]-'0']--;
                        m--;
                    }
                    if(m == 0)break;
                }
                if(m == 0)break;
            }
    
            k = 0;
            if(m > 0) ///去除递增序列的后m个未被标记的数字
            {
                for(i = len-1; i >= last; i--)
                {
                    if(vis[str[i]-'0'])
                    {
                        vis[str[i]-'0']--;
                        m--;
                    }
                    if(m == 0)break;
                }
                //if(m == 0)break;
            }
    
            for(i = len-1; i >= 0; i--)///求最小所以大的数字要尽量放后面
            {
                a = str[i]-'0';
                if(vis[a] > 0)
                {
                    s[k++] = a+'0';
                    vis[a]--;
                }
            }
            k--;
            ///s数组为删除之后的最小数(需要倒序输出)
            while(s[k]=='0' && k > 0) k--;
            for(i = k; i >= 0; i--)
                printf("%c", s[i]);
            if(k == -1) printf("0");
            printf("
    ");
        }
        return 0;
    }
    
  • 相关阅读:
    【ABAP】
    【Ebs】-日记账导入优化
    【EBS】-日记账审批相关知识点
    【LINUX】cron知识小结
    【Oracle】物化视图相关SQL
    【Ebs】EBS12.2.7 REST ISG的配置
    【Oracle】Windows上Oracle数据库的安装
    【EBS】菜单的复制脚本
    《我们内心的冲突》(卡伦•霍尼)读书笔记
    魔方攻略
  • 原文地址:https://www.cnblogs.com/PersistFaith/p/4964766.html
Copyright © 2011-2022 走看看