「LGOJ」删数问题
题意
键盘输入一个高精度的正整数N(不超过250位) ,去掉其中任意k个数字后剩下的数字按原左右次序将组成一个新的正整数。编程对给定的N和k,寻找一种方案使得剩下的数字组成的新数最小。
题解
说是删数问题,其实可以转换为选数问题,也就是选\(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;
}

浙公网安备 33010602011771号