题目
题目描述
键盘输入一个高精度的正整数N(不超过250位) ,去掉其中任意k个数字后剩下的数字按原左右次序将组成一个新的正整数。编程对给定的N和k,寻找一种方案使得剩下的数字组成的新数最小。
输入格式
n(高精度的正整数)
k(需要删除的数字个数)
输出格式
最后剩下的最小数。
输入输出样例
输入 #1 输出 #1
175438 13
4
算法分析
一道经典的贪心题。我们可以一位一位地来删。对于每一次删数字,无论删谁,剩下的位数都相同(都比删掉之前少一位)。那要使删后的数最小,就要尽量让较小的数字排在删后的数的前几位。
拿样例来说:对于175438,如果你删7后的一个数字肯定没有你删7划算,因为15438肯定比17~~~小。
通过观察15438的结构(自己可以在写几个数删删),可以发现我们选择的最优策略是在从左到右的第一个递减区间(如543)删去这第一个递减区间的首位数字。
(这儿感性理解一下:只有这样删去后的数才能不让7出现在前面,也就是这样才能让删去后的数最小)
那如果这个数没有递减区间呢?(如12345)
那就删去末位5呗!
小结
我们的最优策略是:
- 有递减区间的,删去第一个递减区间的首位数字(也就是这个递减区间最大的数字)
- 对于没有的(也就是形如12345的)删去最后一位
看一下代码吧!
Code
#include<bits/stdc++.h>
using namespace std;
int s,cnt;
int a[300];
char ch[300];
int main()
{
ch[0]='1';
while(ch[cnt]>='0'&&ch[cnt]<='9')
{
ch[++cnt]=getchar();
a[cnt]=ch[cnt]-'0';
}
cnt--;
scanf("%d",&s);
for(int i=1;i<=s;i++)
{
for(int j=1;j<=cnt;j++)
{
if(a[j]>a[j+1])//这儿把两种情况合在了一起
//当a[j]是最后一位时,a[j]肯定大于a[j+1]--0呀
{
for(int k=j;k<=cnt-1;k++) a[k]=a[k+1];
cnt--;
a[cnt+1]=0;
break;
}
}
}
int l=1;
while(a[l]==0&&l<=cnt-1) l++;
for(int i=l;i<=cnt;i++) printf("%d",a[i]);
return 0;
}
嗯,这不就好了吗?
大家再仔细回味一下吧!
学习厌倦了?点我有更多精彩哦!