1:活动时间安排的问题
设有N个活动时间集合,每个活动都要使用同一个资源,比如说会议场,而且同一时间内只能有一个活动使用,每个活动都有一个使用活动的开始si和结束时间fi,即他的使用区间为(si,fi),现在要求你分配活动占用时间表,即哪些活动占用该会议室,哪些不占用,使得他们不冲突,要求是尽可能多的使参加的活动最大化,即所占时间区间最大化!
原文:https://blog.csdn.net/effective_coder/article/details/8736718
#include<stdio.h>
#include<string.h>
void GreedyChoose(int len,int s[11],int f[11],int flag[11]);
int main()
{
int i,book[11];
int s[11] ={1,3,0,5,3,5,6,8,8,2,12};
int f[11] ={4,5,6,7,8,9,10,11,12,13,14};
memset(book,0,sizeof(book));
GreedyChoose(11,s,f,book);
for(i = 0; i < 11; i ++)
if(book[i])
printf("%d ",i);
printf("\n");
return 0;
}
void GreedyChoose(int len,int s[11],int f[11],int flag[11])
{
int i,j;
flag[0] = 1;
j = 0;
for(i = 1; i < len; i ++)
if(s[i] > f[j])
{
flag[i] = 1;
j = i;
}
}
类似这种题还有个区间覆盖问题,就是说很多个区间,其中有些是相互覆盖着的,要求去除多余的区间,使剩下的区间占用长度最大,实际就是这个题,只是问法变换了而已!
2.贪心实例之线段覆盖
在一维空间中告诉你N条线段的起始坐标与终止坐标,要求求出这些线段一共覆盖了多大的长度。
#include<stdio.h>
int main()
{
int i,j,len;
int s[10] = {2,3,4,5,6,7,8,9,10,11};
int f[10] = {3,5,7,6,9,8,12,10,13,15};
len = f[0]-s[0];
j = 0;
for(i = 1; i < 10; i ++)
{
if(s[i] >= f[j])
{
len += f[i]-s[i];
j = i;
}
else
{
if(f[i] <= f[j])
continue;
else
{
len += f[i]-f[j];
j = i;
}
}
}
printf("%d\n",len);
return 0;
}
运行结果为13.
3:数字组合问题
设有N个正整数,现在需要你设计一个程序,使他们连接在一起成为最大的数字,比如说3个整数 12,456,342 很明显是45634212为最大,4个整数 342,45,7,98显然为98745342最大
程序要求:输入整数N 接下来一行输入N个数字,最后一行输出最大的那个数字!
题目解析:这道题乍一看挺简单,但仔细分析分析也是有点难度的。简单在好像就是寻找哪个开头最大,然后连在一起就是了,难在如果N大了,假如几千几万,好像就不是那么回事了,要解答这个题目需要选对合适的贪心策略,并不是把数字由大排到小那么简单。
相信冒泡排序都已经很熟悉了,注意看程序中最核心的比较规则是什么,是这一句if(a[j] > a[j+1] ) 他是以数字大小作为比较准则来返回true或者是false,那么我们完全可以改变一下这个排序准则,比如23,123,这两个数字,在我们这个题中它可以组成两个数字 23123和12323,分明是前者大些,所以我们可以说23排在123前面,也就是23的优先级比123大,123的优先级比23小,所以不妨写个函数,传递参数a和b,如果ab比ba大,则返回true,反之返回false。
#include<stdio.h>
#include<math.h>
int compare(int num1,int num2);
int main()
{
int i,j,t,n,a[110];
scanf("%d",&n);
for(i = 1; i <= n; i ++)
scanf("%d",&a[i]);
for(i = 1; i < n; i ++)
for(j = 1; j <= n-i; j ++)
if(compare(a[j],a[j+1]))
{
t = a[j];
a[j] = a[j+1];
a[j+1] = t;
}
for(i = 1; i <= n; i ++)
printf("%d",a[i]);
printf("\n");
return 0;
}
int compare(int num1,int num2)
{
int i,ans1,ans2,k1,k2;
k1 = num1;
k2 = num2;
ans1 = ans2 = 0;
while(num1)
{
ans1 ++;
num1 /= 10;
}
while(num2)
{
ans2 ++;
num2 /= 10;
}
if((k1*pow(10,ans2)+k2) < (k2*pow(10,ans1)+k1))
return 1;
return 0;
}
4:找零钱的问题
在贪心算法里面最常见的莫过于找零钱的问题了,题目大意如下,对于人民币的面值有1元 5元 10元 20元 50元 100元,下面要求设计一个程序,输入找零的钱,输出找钱方案中最少张数的方案,比如123元,最少是1张100的,1张20的,3张1元的,一共5张!
解析:这样的题目运用的贪心策略是每次选择最大的钱,如果最后超过了,再选择次大的面值,然后次次大的面值,一直到最后与找的钱相等。
#include<stdio.h>
int main()
{
int i,j,all,Moneycount,count;
int MoneyClass[6] = {100,50,20,10,5,1};
int MoneyIndex[6] ={0};
Moneycount = count = 0;
scanf("%d",&all);
for(i = 0; i < 6;)
{
if(Moneycount+MoneyClass[i] > all)
{
i ++;
continue;
}
Moneycount += MoneyClass[i];
MoneyIndex[i] ++;
count ++;
if(Moneycount == all)
break;
}
for(i = 0; i < 6; i ++)
if(MoneyIndex[i] != 0)
printf("%d =%d\n",MoneyClass[i],MoneyIndex[i]);
printf("%d\n",count);
return 0;
}