贪心算法——C语言

本文介绍了贪心算法的基本思想,通过活动选择问题和钱币找零问题展示了贪心策略的运用。在活动选择问题中,通过对活动按结束时间排序,尽可能选择最早结束的活动,以达到最大化同时进行的活动数。在找零问题中,优先使用面值大的纸币以减少纸币数量。这两个实例直观地解释了贪心算法如何寻找局部最优以达到全局最优解。
摘要由CSDN通过智能技术生成

习该博主「houjingyi233」的贪心算法而感:
原文链接:https://blog.csdn.net/qq_32400847/article/details/51336300

贪心/贪婪算法的主要思想就是局部最优——>全局最优,这并不是一个比较难理解的概念,然后我经过相关的题目案例发现难点在于求得每一个局部最优解的算法。
心算法的定义:
1.活动选择问题:
有n个需要在同一天使用同一个教室的活动a1,a2,…,an,教室同一时刻只能由一个活动使用。每个活动ai都有一个开始时间si和结束时间fi 。一旦被选择后,活动ai就占据半开时间区间[si,fi)。如果[si,fi]和[sj,fj]互不重叠,ai和aj两个活动就可以被安排在这一天。该问题就是要安排这些活动使得尽量多的活动能不冲突的举行。

#include<stdio.h>
#include<stdlib.h>

struct  Act{
	int start;
	int end;

}act[1000];

/*活动选择问题*/ 

void sort(Act act[],int n);
int explore(Act act[],int n);


int main()
{
	 int n;
	 scanf("%d",&n);
	 for(int i=0;i<n;i++)
	 {
	 	scanf("%d%d",&act[i].start,&act[i].end);
	 }
	 //将每个活动根据其结束时间进行从小到大的排序 
	sort(act,n);
	//根据贪心算法求出选择每个活动的最优时间
	int num=explore(act,n); 
	printf("一天中选择可进行活动最大的数量为:%d",num);
	return 0;
}

void sort(Act act[],int n)
{
		for(int i=0;i<n;i++)
		{
			for(int j=0;j<n-i-1;j++)
			{	
				if(act[j].end>act[j+1].end)
				{
					Act temp=act[j];
					act[j]=act[j+1];
					act[j+1]=temp;
				}
			}
		}
 } 
int explore(Act act[],int n)
{
	int result=1;
	for(int i=0;i<n;i++)
	{
		for(int j=i+1;j<n;j++)
		{
			if(act[i].end<act[j].start)  //所有活动都已根据结束时间从小到大排序,所以现在只需要根据前一个活动的结束时间 , 
			{                            //所以现在只需要根据前一个活动的结束时间大于后一个活动的开始时间即可安排进行。 
				result++;
				i=j;
			}
		}
	}
	return result;
}

2.钱币找零问题
假设1元、2元、5元、10元、20元、50元、100元的纸币分别有c0, c1, c2, c3, c4, c5, c6张。现在要用这些钱来支付K元,至少要用多少张纸币?用贪心算法的思想,很显然,每一步尽可能用面值大的纸币即可。

#include<stdio.h>
#include<stdlib.h>

int main() {
	int m[7]= {1,2,5,10,20,50,100}; //先有纸币的数额
	int k;
	//所找的金额
	int num;          //所需纸币的张数
	while((	scanf("%d",&k))!=EOF) {
		while(k>0) {
			if(k>=100) {
				k-=100;
			} else if(k>=50&&k<100) {
				k-=50;
			} else if(k>=20&&k<50) {
				k-=20;
			} else if(k>=5&&k<20) {
				k-=5;
			} else if(k>=2&&k<5) {
				k-=2;
			} else if(k>=1&&k<2) {
				k-=1;
			}
			num++;
		}
		printf("所需的张数为:%d\n",num);
	}
}

3.再论背包问题
4.多机调度问题
5.小船过河问题
6.区间覆盖问题
给定一个长度为m的区间,再给出n条线段的起点和终点(注意这里是闭区间),求最少使用多少条线段可以将整个区间完全覆盖
注:该代码只能通过部分案例,问题我来日再来解决!!!

#include<stdio.h>
#include<stdlib.h>
//测试数据:8 7   1 6 3 4 3 6 3 7 6 8 2 4 3 5

struct Line {  //表示每条线段的左右区间的值
	int x;
	int y;

};

void sort(Line l[],int n);       //将每一个区间按照左端点递增的顺序排序
int  search(Line l[],int n,int m) ;
int main() {
	//m为区间长度,n为线段条数
	int m,n;
	scanf("%d%d",&m,&n);
	Line l[n];
	for(int i=0; i<n; i++) {
		scanf("%d%d",&l[i].x,&l[i].y);
	}
	sort(l,n);
	int num;
	num=search(l,n,m);
	printf("%d",num);
	return 0;
}

void sort(Line l[],int n) {
	for(int i=0; i<n; i++) {
		for(int j=0; j<n-i-1; j++) {
			if(l[j].x>l[j+1].x) {
				Line temp=l[j];
				l[j]=l[j+1];
				l[j+1]=temp;
			}
		}
	}
}
int  search(Line l[],int n,int m) {
	int i=0;
	int ans=0,max=0,r=l[0].x;
	for(i=0; i<n; i++) {
		if(l[i].x<=r) {
			for(int j=i; j<m; j++) {
				if(l[j].x<=r&&l[j].y>r&&l[j].x>max) {
					max=l[j].y;
					i=j;
				}
			}
			r=max;
			max=0;
			ans++;
		}
		if(r>=m) {
			break;
		}
	}
	if(r<m) {
		return 0;
	} else {
		return ans;
	}

}
  • 13
    点赞
  • 152
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值