贪心算法——1321:【例6.3】删数问题(Noip1994)

在这里插入图片描述

自己写的,没通过

#include<bits/stdc++.h>
using namespace std;

int main(){
	char n[250],no[250],t[250],temp[250];
	int wz[250],flag;
	int s,g=0;
	cin>>n>>s;
	/* 
	if(strlen(n)<=s){	//如果输入的位数小于要删除的位数 
		cout<<'0';
		return 0;
	}
	*/
	for(int i=0;i<s;i++)	       //记录前s个值和下标 
	{
		t[i]=n[i];
		no[i]=i;
	}
	int i,m;	//m记录前t[]数组前m位不变了 
	for(i=s;i<strlen(n);i++){
		char min='a';				//min值为97 
		int wz;
		for(int j=m;j<s;j++){		//分别进行判断  
			if(t[j]<min){
				min=t[j];
				wz=j;				//记住最小值位置 
			}
		}
		if(n[i]<min){				//如果数组t里的所有值都比之后一个数大则结束循环 
			 break;
		}
		else{
			//cout<<t[wz];			//直接输出最小值
			if(t[m]!=min)m++;		//如果t[m]不等于最小值,则t[m]的值就不变了 
			temp[g++]=t[wz];		//记录结果 
			for(int j=wz;j<s-1;j++){ //将t[wz]后的值向前移一位 
				t[j]=t[j+1];
				no[j]=no[j+1];
			}
			t[s-1]=n[i];			//将n[i]放到t[s-1]位,即最后一位 
			no[s-1]=i;
		}
	} 
	for(int k=i;k<strlen(n);k++) temp[g++]=n[k];	//余下的位数直接加到temp数组后面 
	int d=0,b=0; //b用于记录前置0位置 
	while(true){				//去掉可能存在的前置0 
		if(temp[d++]=='0')b++;
		else break;
	}
	for(int l=b;l<g;l++) cout<<temp[l];				//输出结果 
	if(b>=g)cout<<'0';					//如果b大于等于temp数组长度,则说明结果为0 
	return 0;
}

思路:
从前往后找(st,s+i),找到最小的直接输出
st默认为第一个数,后面为前面最小之后的一个数
i的范围为需要最后输出结果的位数
需要考虑前置0的情况

#include<bits/stdc++.h>
using namespace std;

int main(){
	char t[241];
	int  tt[241],s;
	cin>>t>>s;
	int len=strlen(t);
	for(int i=1;i<=len;i++){
		tt[i]=t[i-1]-'0';	//将字符转化为数字 
	}
	bool f=0;	//将f设为false 
	int mi,st=1; 
	for(int i=1;i<=len-s;i++){	//找len-s位 
		mi=10;	//将m设为一个足够大的数,只要比9大都行
		for(int j=st;j<=s+i;j++){ //找最小的 
			if(mi>tt[j]){ 
				mi=tt[j];
				st=j+1; 
			}
		} 
		if(f||mi){		
		//如果f为true或者mi非0(一开始f为false,用于消去前置0)
			if(mi) f=1;	//如果mi非0,将f设为true,用于输出后面的0 
			cout<<mi; 
		}
	} 
	if(!f) cout<<0; //如果f为flase,说明没有结果 
	return 0;
}

https://www.cnblogs.com/sxrekord/p/deletion_problem.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答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为给定的正整数。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值