删数问题(贪心)

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。

  • 6
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值