贪心问题

贪心问题

贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,算法得到的是在某种意义上的局部最优解。
贪心算法不是对所有问题都能得到整体最优解,关键是贪心策略的选择。
贪心算法是一种对某些求最优解问题的更简单、更迅速的设计技术。贪心算法的特点是一步一步地进行,常以当前情况为基础根据某个优化测度作最优选择,而不考虑各种可能的整体情况,省去了为找最优解要穷尽所有可能而必须耗费的大量时间。贪心算法采用自顶向下,以迭代的方法做出相继的贪心选择,每做一次贪心选择,就将所求问题简化为一个规模更小的子问题,通过每一步贪心选择,可得到问题的一个最优解。虽然每一步上都要保证能获得局部最优解,但由此产生的全局解有时不一定是最优的,所以贪心算法不要回溯。

解题策略

贪心算法不从整体最优上加以考虑,所做出的仅是在某种意义上的局部最优选择。使用贪心策略要注意局部最优与全局最优的关系,选择当前的局部最优并不一定能推导出问题的全局最优。贪心策略解题需要解决以下两个问题:
1、该问题是否适合使用贪心策略求解,也就是该问题是否具有贪心选择性质 ;
2、制定贪心策略,以达到问题的最优解或较优解 。
要确定一个问题是否适合用贪心算法求解,必须证明每一步所作的贪心选择最终导致问题的整体最优解。证明的大致过程为:首先考察问题的一个整体最优解,并证明可修改这个最优解,使其以贪心选择开始,做了贪心选择后,原问题简化为规模更小的类似子问题。然后用数学归纳法证明通过每一步做贪心选择,最终可得到问题的整体最优解 。
以上是网页上对贪心算法进行的解释,当然我们不能只停留在理论知识上,我将引用几道常见的贪心算法的例题。

分糖果问题

大家都知道,糖果是孩子们最喜欢的零食,而每一个孩子对糖果的 需求不同,有的孩子喜欢大的糖果,有的孩子喜欢小的糖果,而糖果的大小自然也不同。要求在第一行输入两个数,分别代表有几个糖果和有几个孩子。第二行和第三行分别输入糖果的大小和孩子们的需求度(需求度越大,需要的糖果也就越大),在此处我们定义只有当糖果的大小大于需求度的时候孩子才会被满足。输出一个数代表最多可以满足几个孩子的需求。

题目分析

在我们拿到这一到题之后,我们口语先将糖果和学生分别放入到两个数组中,要是更多的孩子们被满足,肯定需要用最小的糖果去试试看能不能满足需求最小的孩子。由此,我们可以对两个数组进行升序排列,同时定义三个常量c=0,t=0,sum=0,分别代表孩子,糖果和满足需求的孩子的个数。将糖果的大小与孩子的需求进行比较,若满足。则孩子和糖果(c和t)都自增,同时sum++,否则换下一个更大的糖果,即t++。直到遍历完糖果中的每一个元素或者孩子中的每一个元素。

import java.util.Arrays;
import java.util.Scanner;
public class Main {
	public static void main(String[] args) {
		Scanner in=new Scanner(System.in);
		int m,n;
		n=in.nextInt();//糖果的个数
		m=in.nextInt();//孩子的数量
		int T[]=new int[n];
		int C[]=new int[m];
		int i;
		for(i=0;i<n;i++) {
			T[i]=in.nextInt();
		}
		for(i=0;i<m;i++) {
			C[i]=in.nextInt();
		}
		Arrays.sort(T);
		Arrays.sort(C);
		int c=0,t=0;
		int sum=0;
		for(i=0;c<m&&t<n;i++) {
			if(T[t]>C[c]) {
				c++;
				sum++;
			}
			t++;
		}
		System.out.println(sum);
	}
}

主持人选拔

今年是纪念“一二·九”运动第85周年,其中学校比较大型的活动就是“一二·九”大合唱比赛了。今天,我们并不筛选“中国好嗓音”,而是在每个班级中海选主持人,规定主持人必须由一男一女组成,且两人身高之和必须大于等于x。若一个班级中有n名男生,m名女生,给你每个男生和每个女生的身高,求这个班级最多能凑出多少对主持人。

题目分析

和一题目的思路相同,不同的是这个最有解的判断,两种身高元素的和大于一个数,要使更多组满足,肯定需要“高的”+“矮的”,由此,我们将两个数组分别按照升序和降序排列,再去进行判断即可。

import java.util.Arrays;
import java.util.Scanner;
public class Main{
  public static void main(String[] args) {
  	Scanner in=new Scanner(System.in);
  	int n,m,x;
  	n=in.nextInt();
  	m=in.nextInt();
  	x=in.nextInt();
  	int boy[]=new int[n];
  	int girl[]=new int[m];
  	int i;
  	for(i=0;i<n;i++) {
  		boy[i]=in.nextInt();
  	}
  	for(i=0;i<m;i++) {
  		girl[i]=in.nextInt();
  	}
  	Arrays.sort(boy);
  	Arrays.sort(girl);
  	
  	int temp;
  	for(i=0;i<m/2;i++) {
  		temp=girl[i];
  		girl[i]=girl[m-1-i];
  		girl[m-1-i]=temp;
  	}
  	int B=0,G=0;
  	int sum=0;
  	for(;B<n&&G<m;) {
  		if(boy[B]+girl[G]>=x) {
  			G++;
  			sum++;
  		}
  		B++;
  	}
  	System.out.println(sum);
  }
}

以上是我在遇到对贪心问题的时候产生的理解,以后如果遇到类似问题还会持续更新此类问题的题解。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值