题意
给一堆数字,从中删去M个数字并且去掉前导零以后,要求形成的数字最小,问形成的最小数字是多少。
题解
其实是很水的贪心题?好像可以用RMQ进一步优化,不过使用普通的贪心算法就可以达到一个不错的时间。贪心方法很简单,持续选择x[i]>x[i+1]的就可以了。这个是可以证明的,如果删掉i前面的任何一个数字,数字的总位数只会减少一位(其实也可以相当于后面的数字进了一位),这样形成的数字一定不如删掉i更划算。如果删掉i后面的任何一个数字,由于i占用着比较靠前的位置,所以一定不如删掉i,使得比i小的数字占据这个位置更划算。综上所述,删除i是最优选择。
代码
#include <iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<string>
#include<set>
#include<map>
#include<bitset>
#include<stack>
#include<string>
#define UP(i,l,h) for(int i=l;i<h;i++)
#define DOWN(i,h,l) for(int i=h-1;i>=l;i--)
#define W(a) while(a)
#define MEM(a,b) memset(a,b,sizeof(a))
#define LL long long
#define INF 0x3f3f3f3f
#define MAXN 800010
#define MOD 1000000007
#define EPS 1e-3
using namespace std;
char s[1010];
int main() {
int m;
W(~scanf("%s%d",s,&m)) {
int n=strlen(s);
W(m) {
int tag=-1;
UP(i,0,n-1) {
if(s[i]>s[i+1]) {
tag=i;
break;
}
}
if(tag==-1) {
break;
}
UP(i,tag,n-1) {
s[i]=s[i+1];
}
m--;
n--;
}
bool first=true;
UP(i,0,n-m) {
if(first&&s[i]=='0')
continue;
first=false;
printf("%c",s[i]);
}
if(first) {
puts("0");
} else {
puts("");
}
}
}