C++入门必会--删数问题

题目链接

删数问题 - 洛谷https://www.luogu.com.cn/problem/P1106


题目描述

       键盘输入一个高精度的正整数N(不超过250位),去掉其中任意K个数字后剩下的数字按原左右次序将组成一个新的非负整数。编程对给定的N和K,寻找一种方案使得剩下的数字组成的新数最小。

输入

输入两行正整数。

第一行输入一个高精度的正整数N。

第二行输入一个正整数K,表示需要删除的数字个数。

输出

输出一个整数,最后剩下的最小数。

样例组

输入
175438 
4

输出 13

题目思路

        这是一道很经典的贪心题目。

        读入字符串s,然后读入N,紧接着对字符串s进行操作。这样做可以避免麻烦的高精度,从而借助字符串的特点(可以直接进行erase操作)来使题目更加简单。

        以样例为例,我们可以先列一张表格(表示字符串s),来模拟对字符串进行的删数操作。

        最开始的字符串是这样的:

字符串sk=4
175438

        然后我们根据数字比较大小先看首位,从而寻找最前面的逆序对(也就是前面的数比后面大的数对)。

字符串sk=4
175438

        然后可以发现,第一个逆序对是7和5,那么我们可以直接将7删去,从而让这个字符串在删除一个数的情况下最小。 

         以此类推,我们就可以将字符串s变成下表:

字符串sk=1
138

        那这时候该怎么删呢?我们可以用枚举的方法来将删除每个数位后的结果一一列出:

删除1后的结果: 38
删除3后的结果: 18
删除8后的结果: 13
38>18>13

         不难发现,在删除8后的结果最小。当整个字符串都不存在逆序对的时候,末尾的数最大。因此,在这种情况下,我们应该删除末尾的数。

        最后果然得出了正确答案13。


题目解析

        那么该怎么具体实现删数问题呢?

        首先,输入部分一行cin就行了。而循环删数过程,我们可以使用while(k--)来执行。

        而每次删数,先设变量T为s.size()-1(最后一个数的位置),然后遍历字符串,寻找最前面的逆序对,并将T设为逆序对前面一个数的位置,直接切出循环。

        然后在循环外面写一行s.erase(T,1)将字符串的第T位删除。

        最后在while循环外面输出字符串s。

        题目主程序如下:

void cx()
{
   while(k--)//等价于for(int i=0;i<k;i++)
   {
     int t=s.size()-1;
   	 for(int j=0;j<=s.size();j++)
   	 {
   	 	if(s[j]>s[j+1])//找到逆序对
   	 	{
   	 		t=j;//储存逆序对的前一位
   	 		break;
		}
   	 }   	 
   	 s.erase(t,1);//删除
   }
}

        这一篇将会是题目解析/思路与标程分离的第一篇。之后与C++有关的内容都会将标程进行分离。涨粉1个,更新一篇!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值