【贪心算法】两个经典题

ps:概念等问题见上一篇文章【贪心入门】

http://t.csdn.cn/sdhTz

一.删数问题

        1.1题目

P1106 删数问题 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)P1106 删数问题 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

题目描述

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

输入格式

输入两行正整数。

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

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

输出格式

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

样例输入:

175438 
4

样例输出:

13

        1.2思路 :

         若同位数相比,易知19876<51234;固只需要保证高位小,则数一定小。所以想要找最小值只需要保证高位都尽量小,这不刚好是贪心思想?(eg:要删掉一位数,n=3211,则删掉首位3即可;n=2431,则删4即可。要删掉两位数,n=32111,则删掉32;n=23441,则删掉44)就这样删掉高位的大数。

        1.3核心代码:

​
for(int w=1;w<=s;w++){  //一共删除s位数 
		for(int i=0;i<len-1;i++){  
			if(a[i]>a[i+1]){     //找到高位有大数就立马删掉 
				for(int j=i;j<len-1;j++){  //把这个大数覆盖掉 
					a[j]=a[j+1];
				}
				len--;  //现在还有几位数 
				break;
			}
		}
	}

​

        1.4完整AC代码 

#include<iostream>
#include<cstring>
using namespace std;
char n[1001];  //字符串用来输入高精度数
int a[1001];  //用来存储数据 
int main(){
	int s;  //要删除的位数 
	cin>>n>>s;
	int len=strlen(n);  //一共有几位数 
	int len1=len-s;    //删除后有几位数 
	for(int i=0;i<len;i++){  //字符串转数组 
		a[i]=n[i]-'0';
	}
	for(int w=1;w<=s;w++){  //一共删除s位数 
		for(int i=0;i<len-1;i++){  
			if(a[i]>a[i+1]){     //找到高位有大数就立马删掉 
				for(int j=i;j<len-1;j++){  //把这个大数覆盖掉 
					a[j]=a[j+1];
				}
				len--;  //现在还有几位数 
				break;  //删一次就行了,进入下一次的删除循环 
			}
		}
	}
	while(len!=len1){ //处理23456不好比较大小,删数的情况 
		len--;
	}
	int start=0;
	while(a[start]==0 &&start<len-1)  //处理首位的0 
		start++;
	for(int i=start;i<len;i++){
		cout<<a[i];
	} 
	
	return 0;
}

二.活动安排问题

2.1题目

        题目描述

现在有n个活动将要举办,分别有每个活动的起始时间和终止时间,请求出最多能参加几个。

        输入格式

第一行有一个整数n,表示有n个活动

随后的n行各有两个整数分别是每个活动的起始和终止时间

        输出格式

一个整数,表示最多能参加几个活动

        输入样例

6

3 6

2 4

5 7

1 5

5 8

8 10

        输出样例

3

2.2思路

        稍微有点难理解,多看看就懂了。

        因为想要参加的活动达到最多,当每次活动的终止时间都最早时(当相等时就起始时间越晚越好),则就可以参加更多的活动。这里又是贪心的思路。

2.3核心代码

for(int i=1;i<n;i++){
		if(a[i].start>=last){
			ans++;
			last=a[i].end;
		}
	}

2.4完整AC代码

#include<iostream>
#include<algorithm>
using namespace std;
struct activity{
	int start;   //起始时间 
	int end;	//终止时间 
}a[1001];
//终止时间在前面的优先,若相同,起始时间晚的优先 
bool cmp(activity a,activity b){
	if(a.end!=b.end){
		return a.end<b.end;
	}else{
		return a.start>b.start;
	}
	
}
int last,ans=1;
int main(){
	int n;
	cin>>n;
	for(int i=0;i<n;i++){
		cin>>a[i].start>>a[i].end;
	}
	sort(a,a+n,cmp);
	last=a[0].end;
	for(int i=1;i<n;i++){
		if(a[i].start>=last){
			ans++;
			last=a[i].end;
		}
	}
	cout<<ans<<endl;
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值