Java教程

算法入门之贪心算法笔记

本文主要是介绍算法入门之贪心算法笔记,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

  (一)从现金找零理解什么是贪心思想 

        在以前移动支付不是很普及的时代,找零几乎天天伴随着我们的生活。假设你去商店买东西,需花费11元,而你是个小富翁,口袋里只有百元毛爷爷。售货员找零应该怎么找呢?找89张1元多好,都说不能把鸡蛋放在同一个篮子里嘛-.-。开个玩笑,售货员会先找一张50元,然后是一张20元,10元,5元,最后是4张1元,搞定。那为什么不找89张1元呢,那多费劲啊,找费劲,拿也费劲,虽说钱不嫌多,但也扛不住这么拿把。所以通常我们都是从面值相对大的开始找起,而这种找零思路就是贪心思想的一个体现。                                                                                           

       (二)贪心算法的基本要素

(1)贪心选择性质

         从上面的问题我们可以看出,贪心算法并不从整体最优上加以考虑,我们做的每一步只是某种意义上的局部最优选择,而这种策略依然能得到整体的最优解。那么我们怎么判断这种策略能100%的得到整体的最优解,换句话说,怎么样有可能用到贪心算法呢。这就要看贪心选择的一个重要要素了:贪心选择性质。

         贪心选择性质是这样定义的:所求的问题可以通过一系列局部最优的选择(即贪心选择)来达到。

       要想证明一个问题有贪心选择性质,可以考虑按照一下步骤执行。

     (1)考虑证明一个问题的整体最优解有可修改性,如果具有可修改性的话,这个问题就有了贪心选择开始的条件。

     (2)这样通过一系列的贪心选择后,原问题简化为更小的子问题。

     (3)然后用数学归纳法证经过每一步的贪心选择,这样最终可以得到问题的最优解。

(2)最优子结构性质

         这一点和动态规划类似,这是该问题可以用动态规划和贪心求解的关键特征。但与动态规划不同的是,动态规划是自底向上求解问题,而贪心则是自顶向下迭代求解问题,每一次通过贪心选择都会使问题变成更小的子问题。

(三)通过实例理解贪心思想

(1)删数问题

【题目描述】
输入一个高精度的正整数n,去掉其中任意s个数字后剩下的数字按原左右次序组成一个新的正整数。编程对给定的n和s,寻找一种方案使得剩下的数字组成的新数最小。
输出新的正整数。(n不超过240位)
输入数据均不需判错。
【输入】
带处理的正整数n
删除的位数k
【输出】
最后剩下的最小数。
【输入样例】
175438
4
【输出样例】
13

        这个问题就用到了贪心的思想,我们要从高位向低位逐位搜索,若各位数字递增,则删除最后一个数字,否则删除第一个递减区间的首字符。然后回到高位删除下一位数字。以此类推得到结果。

代码如下:

#include<iostream>
using namespace std;
void solution(int a,int k)
{
	int n=0,flag=0;
	int m[100]={0x00a};
	while(a!=0)
	{
		m[++n]=a%10;
		a=a/10;
	}
//	for(int i=n;i>=1;i--)
//	cout<<m[i]<<" ";
//	cout<<endl;
	int c=k;
	while(k)
	{
		for(int i=n;i>=1;i--)
		{
			if(m[i]>m[i-1]||m[i-1]==0x00a)
			{
				for(int j=i;j>=1;j--)
				m[j]=m[j-1];
				break;
			}
//			cout<<m[i]<<" ";
		}	
		k--;
//		cout<<endl;
	}
	cout<<endl;
	for(int i=n;i>=1;i--)
	if(m[i]>=0&&m[i]<=9)
	cout<<m[i];
}
int main()
{
	int a,k;
	cin>>a>>k;
	solution(a,k);
	return 0;
}

(2) 会场安排问题

假设要在足够多的会场里安排一批活动,并希望使用尽可能少的会场。设计一个有效的贪心算法进行安排。对于给定的k个待安排的活动,计算使用最少会场的时间表。
输入
第1行有1个正整数k,表示有k个待安排的活动。下来的k行中,每行有2个正整数,分别表示k个待安排的活动的开始时间和结束时间。时间以0点开始的分钟计。
输出
将计算出的最少会场数输出到。
样例输入
5
1 23
12 28
25 35
27 80
36 50
样例输出
3

    这个问题我们首先向一个会场内尽可能的安排活动,直到该会场无法被安排任何活动后再安排下一个会场,直到所有的活动被安排完毕。

代码如下:

#include<iostream>
using namespace std;
struct t
{ 
	int begin,end;
	bool flag;
};
void solution(int n,t *a)
{
    int num=n,temp=0,count=0;
	while(num>0)
	{
		for(int i=1;i<=n;i++)
		{
			if((a[i].begin>temp)&&(a[i].flag==0))
			{
				temp=a[i].end;
				a[i].flag=1;
				num--; 
			}
		}
		temp=0;
		count++;
	}
	cout<<count<<endl;
}
int main()
{
	int n,result;
	cin>>n;
	t a[n+1];
	for(int i=1;i<=n;i++)
	{
		cin>>a[i].begin>>a[i].end;
		a[i].flag=0;
	}
	solution(n,a) ;
	return 0;
}

这篇关于算法入门之贪心算法笔记的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!