1.题目
输入一个高精度的正整数n(≤240位),去掉其中任意s个数字后,剩下的数字按原左右次序组成一个新的正整数。编程对给定的n和s,寻找一种方案,使得剩下的数字组成的新数最小。
输入
第1行:一个正整数n;
第2行:s(s<n的位数).
输出
最后剩下的最小数。
- 输入样例
175438
4 - 输出样例
13
2.思想
这是一个大力贪心的问题,要删掉k个数字,我们每次删掉一个数字,都要确保问题处于最优解,即删掉这个数字后,剩下数字组成的新数是最小的,这样重复k遍即得到最优解
3.易错点
往往做题者(比如我)有点贪过了,怎么讲,每次都要在这一堆数中删掉最大的一个,当WA了几遍后,我获得了一个反例
.
- 125483 删掉一个数字,若我们删掉最大的,即成为12543,但实际上正确答案是12483,12543并不是最优解
4.如何得到局部最优解从而得到整体最优解呢?
- 通过上述反例我们发现5是一个上升序列的最后一位,那么我们猜想是不是每次都要删掉上升序列的最后一位,经过数次举例
(1) 356124 最优解为35124
(2)612432 最优解为12432
(3)1753245 最优解为153245
……
我们的猜想是立得住脚的,在打比赛中我们不必如此谨慎,有了想法举几个例子合适,就直接开敲就得
5.代码实现
#include <iostream>
#include<bits/stdc++.h>
using namespace std;
char a[300];
int k,i,j,flag;
int main()
{
cin>>a>>k;
int n=strlen(a);
for(i=0;i<k;i++)
{
for(j=0;j<n-1-i;j++)
{
if(a[j]>a[j+1])
{
break;
}
}
for(;j<n-1-i;j++)
{
a[j]=a[j+1];
}
}
for(i=0;i<n-k;i++)
{
if(a[i]=='0'&&!flag)continue;
else
{
flag=1;
cout<<a[i];
}
}
cout<<endl;
return 0;
}
6.解读
1.寻找上升序列的末位,即用a[j]与a[j+1]判断,若前者大于后者,则前者即为我们要删掉的数,那么从a[j]开始,把后面的向前移动,就可以删掉它。
2.最后输出的时候,当出现第一个不为0的数时,flag=1,目的是不输出前面的0,若无该步骤,若输入
000175438
4
则会输出 00013,肯定WA。