算法入门之贪心算法笔记
作者:互联网
(一)从现金找零理解什么是贪心思想
在以前移动支付不是很普及的时代,找零几乎天天伴随着我们的生活。假设你去商店买东西,需花费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;
}
标签:选择,入门,int,问题,算法,会场,最优,贪心 来源: https://blog.csdn.net/aller_665720/article/details/121322668