「LGOJ」删数问题

题意

键盘输入一个高精度的正整数N(不超过250位) ,去掉其中任意k个数字后剩下的数字按原左右次序将组成一个新的正整数。编程对给定的Nk,寻找一种方案使得剩下的数字组成的新数最小。

Link

题解

说是删数问题,其实可以转换为选数问题,也就是选\(n-k\)个数

根据贪心原理,越是小是数,就要扔到前面

比如说

50074897
2

0放在最前面是最优的

高位尽可能的选小的

所以对于一个数\(f[i]\)如果它比后面的数大

那么我们应该把这个数删去

越靠前越早删

一个让这串数字越小,它的高位数就得越小

我们每次删除要使得删除后的数高位尽量的小

每一次删除时,从最高位开始向低位数遍历

当遇到的一位数比它的更高位更小时

我们就删除它的更高一位,让这个更小的数“篡位”,就可以保证这串数更小

下一次删除时,要也从新从最高位开始

Code

#include <bits/stdc++.h>
using namespace std;

#define RE register

string s;
int k,cnt,n,f[300];
bool used[300]={false};

stack <int> p;


inline void fread(int &x){
    x=0;
    int f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-')f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        x=(x<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    x*=f;
}

int main(){
    cin>>s;
    fread(k);
    if(s.length()<k)cout<<0;
    n=s.length();
    for(RE int i=0;i<n;i++){
        f[i]=s[i]-48;
    }
    int e=0;
    while(k--){
        for(RE int i=0;i<n;i++){
            if(f[i]>f[i+1]){
                for(RE int j=i;j<=n;j++)f[j]=f[j+1];
                break;
            }
        }
        n--;
    }
    int flag=0;
    if(n==1){
        printf("%d",f[0]);
        return 0;
    }
    for(RE int i=0;i<n;i++){
        if(f[i]==0&&flag==0){
            continue;
        }else{
            printf("%d",f[i]);
            flag=1;
        }
    }
    return 0;
}
posted @ 2021-08-13 11:30  sushitong  阅读(198)  评论(0)    收藏  举报