删数问题
题目描述
键盘输入一个高精度的正整数 N N N(不超过 250 250 250 位),去掉其中任意 k k k 个数字后剩下的数字按原左右次序将组成一个新的非负整数。编程对给定的 N N N 和 k k k,寻找一种方案使得剩下的数字组成的新数最小。
输入格式
输入两行正整数。
第一行输入一个高精度的正整数 n n n。
第二行输入一个正整数 k k k,表示需要删除的数字个数。
输出格式
输出一个整数,最后剩下的最小数。
样例 #1
样例输入 #1
175438
4
样例输出 #1
13
解题思路
这道题我一开始想的是可不可以排序,把最大的几个数给删掉,后来发现不行,因为题目要求左右次序得不变,例如,考虑141519 2
这个输入,如果直接删掉两个最大的得到是1411
,实际上最小的应该是1119
,应该删掉 4 和 5,实际上,可以发现被删的数都是一个山峰,而我们要做的就是把后面比这个山峰小的数移到前面来,也就是我们需要删掉
s
[
i
]
≥
s
[
i
+
1
]
s[i] \geq s[i+1]
s[i]≥s[i+1],需要注意的是最后前导0的处理,例如:00000123,应该输出123
代码
#include<iostream>
#include<string>
using namespace std;
int main()
{
string s;
cin >> s;
int k;
cin >> k;
int len = s.length();
int a = len, b = k;// 保护初始值,最后需要输出 a-b个字符
s = " " + s;
while(k--)
{
for(int i=1;i<len;i++)
{
if(s[i]>s[i+1])//若出现山峰
{
for(int j=i;j<len;j++)//后面的字符往前移
{
s[j] = s[j+1];
}
len--;
break;
}
}
}
int i = 1;
while(i<=len&&s[i]=='0') i++,b++;//对前导0的处理,这里的b++相当于把0删掉了
if(i==len+1) cout << 0;//0000000 最后输出0
else
{
for(int j=i, cnt=0;cnt<a-b;cnt++,j++) cout << s[j];
}
return 0;
}