NOIP1994」删数问题

删数问题

题目描述

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

输入格式

输入两行正整数。

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

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

输出格式

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

样例 #1

175438 
4
13

找到num[i]>num[i+1],这个就是每次剔除中的最小值,再将其后移,len--

直到剔除的数cnt大于等于k退出循环,如果不存在num[i]>num[i+1],退出循环,不存在num[i]>num[i+1],就代表num就是从小到大排序,此时剔除的数小于k,将len=len-(k-cnt)

如果剔除的数的个数大于数组中非0的个数,直接返回0

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 1000;
int num[N];
char a[N];
int main() {
    int k=0,cnt;
	cin >> a;
	cin >> k;
	int len = strlen(a);
	for (int i = 0; i <len; i++) num[i] = a[i]-'0';
	//for (int i = 0; i <strlen(a); i++) cout << num[i] << " ";
	cnt = 0;
	//为要选出来的数字,选出来的数字就置为-1
	int z_number = 0;//大于0的数字的个数
	int number = len - k;//输出的个数
	int flag = 0;//目前已经输出的个数
	for (int i = 0; i < len; i++) {
		if (num[i] > 0) {
			z_number++;
		};
	};
	if (z_number > k) {
		while (cnt < k) {
			int flag = 0;
			for (int i = 0; i < len - 1; i++) {
				if (num[i] > num[i + 1]) {//剔除第一个锋 就是第一个num[i]>num[i+1]
					flag = 1;
					for (int j = i; j < len - 1; j++) {
						num[j] = num[j + 1];
					};
					num[len - 1] = -1;
					len--;
					cnt++;
					if (cnt >= k)break;
					break;//找到一次锋就退出
				};

			};
			if (flag == 0)break;//没有峰就退出
			//cout << cnt<<endl;
			/*for (int i = 0; i < len; i++) {
				cout << num[i] << " ";
			};*/
		};

		if (cnt < k) {
			len -= (k - cnt);
		};
		int start = 0;
		for (int i = 0; i < len; i++) {
			if (num[i] > 0) {
				start = i;
				break;
			};
		};
		for (int i = start; i < len; i++) {
			cout << num[i];
		};
	}
	else {
		cout << 0;
	};
	cout <<endl;
	return 0;
};

ac了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 这道题目是一个经典的删数问题,给定一个由数字组成的序列,每次删除其中一个数字,直到序列为空或者只剩下一个数字。要求在删除的过程中,每次删除的数字的下标与前一个删除的数字的下标之差都不等于给定的数m。 我们可以使用模拟的方法来解决这个问题,具体来说,我们可以使用一个数组来存储序列中的数字,然后使用一个指针来记录当前需要删除的数字的下标。每次删除一个数字后,我们可以将指针向后移动m个位置,然后再删除下一个数字,直到序列为空或者只剩下一个数字为止。 需要注意的是,当指针向后移动m个位置后,可能会超出数组的范围,此时我们需要将指针重新指向数组的开头,然后再继续删除数字。 另外,我们还需要记录每次删除的数字的下标,以便最后输出删除的顺序。 最终,我们可以得到一个删除数字的顺序,然后按照这个顺序输出原始序列中的数字即可。 总之,这道题目需要我们使用模拟的方法来解决,需要注意指针的移动和数组下标的处理。 ### 回答2: 删数问题是一个非常经典的问题,也经常出现在编程竞赛中。问题的描述是这样的:给定一个正整数序列,要求将其中K个数字删除,使得得到的剩余的数字组成的新整数最小。该问题的数列可以用数组A来表示,删除的数字个数为K。 解决这个问题的核心思想是贪心。我们可以从左到右扫描整个数列,每次删除比当前数字大的左邻居,直到删除的数字个数达到K为止。具体的算法如下: 1. 创建一个空的数组result来保存最后的结果。 2. 从左到右扫描数组A,对于每个数字A[i],如果result不为空且result的最后一个数字比A[i]大,说明A[i]是一个可以删除的数字,将它从result中删除。 3. 将A[i]添加到result的末尾。 4. 如果删除的数字个数还没有达到K,继续执行步骤2和步骤3。 5. 将result中的数字组合成一个新的整数。 通过这个算法,我们可以得到一个最小的新整数。这是因为我们每次都删除了当前位置左边的比它大的数字,使得结果尽可能地小。另外,由于我们从左到右扫描整个数列,所以得到的结果也是按照原数列顺序的。 在实现这个算法时,需要注意的是边界条件。如果K等于0,则不需要删除任何数字,直接将原数列中的数字组合成一个新的整数即可。如果K大于等于原数列的长度,那么删除所有的数字后得到的结果应该是0。 总之,通过贪心算法,我们可以解决删数问题,得到一个最小的新整数。 ### 回答3: 题目要求解决的是一个删数问题noip1994)。给定一个正整数n,每次删除其中一位数字,直到剩下一个数字为止。我们需要找到最后剩下的数字。 针对这个问题,我们可以使用一个循环队列来解决。首先,将数字1到n依次入队列。然后,每次出队一个数字,将其删除,再将其放回队列的尾部。重复这个过程,直到队列只剩下一个数字为止。最后剩下的数字即为解答。 为了实现该算法,我们可以使用循环队列的数据结构和相应的操作。我们可以使用一个数组来实现队列,同时使用两个指针front和rear来表示队列的头和尾。具体操作如下: 1. 初始化队列,将数字1到n依次放入数组中,并将队头指针和队尾指针分别设置为0和n-1。 2. 当队头指针不等于队尾指针时,重复以下步骤:取出队头数字,将队头指针加1,然后将这个数字删除。 3. 将队头数字加入队尾,并将队尾指针加1。如果队尾指针到达数组的末尾,将其设置为0。 4. 重复步骤2和3,直到队头指针等于队尾指针。此时队列只剩下一个数字,输出该数字。 通过以上算法,我们可以很方便地解决这个删数问题。这个算法的时间复杂度为O(n),其中n为给定的正整数。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值