题目描述
键盘输入一个高精度的正整数 n(不超过 250250 位),去掉其中任意 k 个数字后剩下的数字按原左右次序将组成一个新的非负整数。编程对给定的 n 和 k,寻找一种方案使得剩下的数字组成的新数最小。
输入格式
输入两行正整数。
第一行输入一个高精度的正整数 n。
第二行输入一个正整数 k,表示需要删除的数字个数。
输出格式
输出一个整数,最后剩下的最小数。
输入输出样例
输入 #1复制
175438 4
输出 #1复制
13
说明/提示
用 len(n) 表示 n 的位数,保证 1≤len(n)≤250。
如果博客这里看不清(可以看这里)
算法分析
第一步根据题目要求输入高精度正整数n和删掉数字的个数k。大家这里要注意因为这道题是一道高精度算法的题目,所以一定要用字符串string类型来进行n的输入,方便逆序存储。本题因为要求删数后最小的数,所以用一个flag(标记)来记录当前数字是否为最小。接着求字串的length(长度),然后逆序转存。那么删掉的数还剩下几位呢?就要用当前长度-删掉的长度(k)。cnt负责记录当前数字的长度,需要随时更新。设置t为一个最小值下标。while循环,只要当前长度小于最后删完数后的长度,我们就假设最小为t。从t到k+t,打擂台的方式找到最小数的下标。寻找完之后,判断为最小,并将flag变成true(flag=true)。那么只要flag为true,那么就代表当前数字为最小的删数结果,所以直接输出。如果flag不为true,那么就更新已经删了多少数(k)、最小下标(t)、和位数(cnt)。如果while循环结束了的话,flag还为false,那么输出0。
代码实现
#include<iostream>
#include<string>
using namespace std;
int k,a[260];
string s;
bool f=false;
int main(){
cin>>s>>k;
int len=s.length();
for(int i=1;i<=len;i++) a[i]=s[i-1]-'0';
int r=len-k;
int t=1,cnt=0;
while(cnt<r){
int minn=t;
for(int i=t;i<=k+t;i++){
if(a[minn]>a[i]) minn=i;
}
if(a[minn]) f=true;
if(f) cout<<a[minn];
k-=minn-t;
t=minn+1;
cnt++;
}
if(!f) cout<<0;
return 0;
}
总结
本题考查的是高精度逆序转存以及字符串的灵活运用。难点在于如何逆序转存,我针对这一点总结了方法:
第1步:求出字串长度
第2步:从1到字串长度(或从0到字串长度-1)遍历
第3步:套用公式——a[i]=s[i-1]-'0'