目录
题目描述
键盘输入一个高精度的正整数NN(不超过250250位) ,去掉其中任意kk个数字后剩下的数字按原左右次序将组成一个新的正整数。编程对给定的NN和kk,寻找一种方案使得剩下的数字组成的新数最小。
输入格式
nn (高精度的正整数)
kk(需要删除的数字个数)
输出格式
最后剩下的最小数。
输入输出样例
输入 #1复制
175438
4
输出 #1复制
13
分析:
- 首先:要让剩余的数最小,由于删的个数是确定的,即剩余的个数是确定的。当高位数字越小时,得到剩余的数字就越小。如此便得到此题的关键。
- 若要从长度为len的数中,删掉m个数字。首先如何确定要保留的最高位数字?
如果从34125中删掉2个数,显然最高位是1
如果从31245中删掉2个数,显然最高位仍然是1
如果从34215中删掉2个数,最高位最小只能是2
由此得到结论:第一位数字要从前m+1个数中选择一个最小的,前面的删掉。
- 同样的,第二位数字的选择和第一位是一样的道理。如果此时m已经用完,直接把后面的数拼接到结果数组中即可。否则仍按照上述规则寻找。
- 如果仅想到上面这些,并不能AC。原因是0的存在。。。。。。。
举个栗子:
从50074897中删除2个。答案是4897.
如果仍然按上述规则写,答案却是004897,此时,只需要考虑保存答案数组时,特判一下是否是0即可。
- 最后,把上面的全做完了,但。。。。。仍然不能AC。。。。。。。TMD!!!
再举个梨子,从10000中删除两个数。答案是0。按照上述规则来写,最后没有输出,因此,特判一下结果数组的长度,如果最后结果数组的长度是0,直接输出0.
代码如下:
#include <bits/stdc++.h>
using namespace std;
const int MAX = 255;
char str[MAX],res[MAX];
int N;
int main() {
gets(str);
scanf("%d",&N);
int x = 0;
while (str[x]=='0') x++; //清空一下给出数字的前导0
if(x) strcpy(str,str+x);
int countRes=0,cut=0;
for(int i=0; i+N+1 < strlen(str); i++) {
if(N==0) {
strcpy(res+countRes,str+i); //已经删完,把后面的数拼接过来即可
break;
}
int bk=i;
for (int j = 0; j < N; ++j) {
if(str[i+1+j]<str[bk]) {
bk=j+1+i;
}
}
N-=bk-i; //此次需要删除多少个,刷新一下N
if(str[bk]!='0'){
res[countRes++]=str[bk]; //特判,如果不是0才能添加到结果数组中
}
i=bk; //恢复i的索引。
}
if(countRes) puts(res);
else puts("0");
}