删数问题 NOI994(贪心)

本文介绍了一种解决高精度正整数去S位数求最小剩余数的问题,通过贪心策略和string类型操作,作者分享了代码实现并解释了策略。重点在于理解如何选择删除位置以保持剩余数的最小化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述

输入一个高精度的正整数N,去掉其中任意S个数字后剩下的数字按原左右次序组成一个新的正整数。编程对给定的N和S,寻找一种方案使得剩下的数字组成的新数最小。
输出新的正整数。(N不超过240位)输入数据均不需判错。

输入格式:

n
s

输出格式:

最后剩下的最小数。

输入输出样例

输入样例#1:

175438
4

输出样例#1:

13

提示信息

由于正整数n的有效数位为240位,所以很自然地采用字符串类型存贮n。那么如何决定哪s位被删除呢?是不是最大的s个数字呢?显然不是,大家很容易举出一些反例。为了尽可能逼近目标,我们选取的贪心策略为:每一步总是选择一个使剩下的数最小的数字删去,即按高位到低位的顺序搜索,若各位数字递增,则删除最后一个数字;否则删除第一个递减区间的首字符,这样删一位便形成了一个新数字串。然后回到串首,按上述规则再删下一个数字。重复以上过程s次为止,剩下的数字串便是问题的解了。

看完题目要删数,我立马就想到用string来做,因为string可以用函数erase()来做,简单方便

有些人说用char也可以,我认为不够方便,因为char没有计算机本身具有的删除的函数

每一次都要删掉第一个升序数列的最高峰,才能保证最后删完的数是最小的

非常简单,代码如下:

CODE

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
using namespace std;
int len,i,s,b;
string a;
int main()
{
	cin>>a>>s;
	len=a.size();
	while(s>0)
	{
		s--;
		b=1;
		for(i=1;i<len;i++)
		{
			if(a[i]<a[i-1])
			{
				a.erase(i-1,1);
				b=0;
				break;
			}
		}
		if(b)
			a.erase(len-1,1);
		len--;
	}
	while(a[0]=='0')
	{
		len--;
		a.erase(0,1);
	}
    if(len==0)
        cout<<0;  
	cout<<a;
	return 0;
}

删数后要将前面的0删掉再输出(也可以变更开始值【第一个字符的下标】),否则它不是一个正常的数。

注意,有可能删完后是0,所以我们要加一个判断!!!

如果有错,请大佬指点!

点赞关注,谢谢!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值