SDUT 2072 删数问题

1.题目

删数问题
Time Limit: 1000 ms Memory Limit: 65536 KiB
Problem Description
键盘输入一个高精度的正整数n(≤100位),去掉其中任意s个数字后剩下的数字按照原来的左右次序组成一个新的正整数。编程对给定的n与s,寻找一种方案,使得剩下的数字组成的新数最小。
Input
输入有多组 每组包括原始数n,要去掉的数字数s;
Output
输出去掉s个数后最小的数
Sample Input

178543 4

Sample Output

13

2.正确代码

#include <iostream>
#include <string>



using namespace std;

int main()
{
    string a;
    int k,i;


    while(cin >> a >> k)
    {
        while(k--)
        {
            i=0;
            while(i<a.length()&&a[i]<=a[i+1]) i++;
            a.erase(i,1);
        }

        //对字符串零进行处理。

            while(a[0]=='0'&&a.length()!=1)
                a.erase(0,1);

        cout << a << endl;
    }


    return 0;
}

3.代码解读:

首先,我们先要明确贪心算法的核心,然后再来分析这个问题设置一个正确的贪心算法。
如何设计最小数呢?
我们先从广义上理解这个。
1.当然是删除最大的啦。
2.之后,将这些数字从小到大排列起来。
当这一串数字固定时如何来删除呢?
1.思考一个关键问题,对一个数来讲,其大小和什么有关?难道仅仅是取决于最大数吗?当然不是啦,而是取决于最高位的大小啊。
2.所以,对于一个数来讲,其每位数的最大值是次要的,而其数字所在的权位才是重要的。
3.好,既然谈到权位,对于一个相对位置已经固定下来的数字来讲,如何让它值最小呢?答案当然是尽量是权位越高的数字越小
4.只要你理解上面的那句话,那么表现在数字上是升序排序,这是非常重要的。我们只要尽量保证这串数字是升序排序,那么就说明,在当下是最优选择,如果删除目前这位,那么会导致后面的更大的数字来占据这个权位,那么这个数会变大。
5.还有一点,你是应该明确的,那就是,我们只能做到删除数字,无法添加数字,也不能对数字的相对位置做出更改。所以,我们是当下的最优解,我们尽量保证是升序即可,如果发现降序数字,我们就要删除这个最大值,如 1 3 2 我们要删除3,让降序后面更小的数来补齐这个位,会让数字变得更小。
6.所以,我们所做出的一切操作都是为了让数字变得更小,当我们发现一个降序,可以让数字变的更小,所以,我们就要立刻行动起来,把更小的数掉到权更大的位来使数字变得更小,就是这个样子,很好理解。
7.如果整个数字满足升序了,因为我们还要删除数字,这时,我们应该删除哪个呢?因为升序,我们如果删除其中的任何一个,那么后面的比它大的数来补上,权位会变大,这样就会让数变大!如何不用补呢?答案很简单,就是对最后一位来进行删除,所以这个整体的算法就解决出来了。

处理细节

对于C++,我们要明确如何删除字符串类型的单个字符,同时,我们还应该理解如何对零的处理,这个是有很多技巧的,比如10002删除两个数,最后应该为0,必须保证字符串至少有一个为一个,就是这个意思,理解就好。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值