在以前移动支付不是很普及的时代,找零几乎天天伴随着我们的生活。假设你去商店买东西,需花费11元,而你是个小富翁,口袋里只有百元毛爷爷。售货员找零应该怎么找呢?找89张1元多好,都说不能把鸡蛋放在同一个篮子里嘛-.-。开个玩笑,售货员会先找一张50元,然后是一张20元,10元,5元,最后是4张1元,搞定。那为什么不找89张1元呢,那多费劲啊,找费劲,拿也费劲,虽说钱不嫌多,但也扛不住这么拿把。所以通常我们都是从面值相对大的开始找起,而这种找零思路就是贪心思想的一个体现。
从上面的问题我们可以看出,贪心算法并不从整体最优上加以考虑,我们做的每一步只是某种意义上的局部最优选择,而这种策略依然能得到整体的最优解。那么我们怎么判断这种策略能100%的得到整体的最优解,换句话说,怎么样有可能用到贪心算法呢。这就要看贪心选择的一个重要要素了:贪心选择性质。
贪心选择性质是这样定义的:所求的问题可以通过一系列局部最优的选择(即贪心选择)来达到。
要想证明一个问题有贪心选择性质,可以考虑按照一下步骤执行。
(1)考虑证明一个问题的整体最优解有可修改性,如果具有可修改性的话,这个问题就有了贪心选择开始的条件。
(2)这样通过一系列的贪心选择后,原问题简化为更小的子问题。
(3)然后用数学归纳法证经过每一步的贪心选择,这样最终可以得到问题的最优解。
这一点和动态规划类似,这是该问题可以用动态规划和贪心求解的关键特征。但与动态规划不同的是,动态规划是自底向上求解问题,而贪心则是自顶向下迭代求解问题,每一次通过贪心选择都会使问题变成更小的子问题。
【题目描述】 输入一个高精度的正整数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; }