贪心算法:
贪心算法着重与一个“最”字,它在每一步的求解中,选择这一步的最佳操作,并希望通过一系列的最优解,从而得到整体的一个最优解。
贪心算法需要满足以下条件:
1、可行的:即它必须满足问题的约束。
2、局部最优:他是当前步骤中所有可行选择中最佳的局部选择。
3、不可取消:即选择一旦做出,在算法的后面步骤就不可改变了。、
可以说,贪心算法在解决这个问题的策略上目光短浅,仅仅依据当前已有的信息就做出选择,并且一旦做出了选择,无论将来有什么结果,这个选择都不会改变。换言之,贪心法并非从总体最优考虑,它所做出的选择仅仅是在某种意义上的局部最优。贪心算法对于大部分的优化问题都能产生最优解,但不能总获得总体最优解,通常能够获得近似最优解。贪心算法是一条路走到底,没有分支,这也导致了它与动态规范等其他算法相比运行速度较快并且空间也较小。
但要注意,并不是所有题都可以用贪心算法求解。
例题:
导弹拦截
按输入顺序每次在数组中选择一个元素并记录其距离第一个点或第二点的距离,再在剩下的值中选择距离第一个点或第二个点距离最大的元素,再进行不断比较。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
struct one
{
int a;
int b;
}*p,temp;
int a,b,c,d,n,min;
void input();
int big1(int y);
int big2(int y);
void two();
int main(void)
{
input();
two();
printf("%d",min);
return 0;
}
void input()
{
int i,x,y;
scanf("%d %d %d %d",&a,&b,&c,&d);
scanf("%d",&n);
p=(struct one*)malloc(n*sizeof(struct one));
for(i=0;i<n;i++)
{
scanf("%d %d",&x,&y);
p[i].a=(x-a)*(x-a)+(y-b)*(y-b);
p[i].b=(x-c)*(x-c)+(y-d)*(y-d);
}
}
int big1(int y)
{
int i,x=0;
for(i=0;i<y;i++)
{
if(p[i].b>x)
{
x=p[i].b;
}
}
for(i=y+1;i<n;i++)
{
if(p[i].b>x)
{
x=p[i].b;
}
}
return x;
}
int big2(int y)
{
int i,x=0;
for(i=0;i<y;i++)
{
if(p[i].a>x)
{
x=p[i].a;
}
}
for(i=y+1;i<n;i++)
{
if(p[i].a>x)
{
x=p[i].a;
}
}
return x;
}
void two()
{
int i;
min=p[0].a+big1(0);
for(i=0;i<n;i++)
{
if(p[i].a+big1(i)<min)
min=p[i].a+big1(i);
if(p[i].b+big2(i)<min)
min=p[i].b+big2(i);
if(p[i].a+big2(i)<min)
min=p[i].a+big2(i);
if(p[i].b+big1(i)<min)
min=p[i].b+big1(i);
}
}
例题:
钱币找零问题
这个问题在我们生活中十分常见,比如要找152元,先找最大的 100元,剩下52元,再找最大的 50元 ,剩下2元,即1元*2。
这里以一元钱找零为例子。
#include<stdio.h>
int main()
{
int m;
int a,b,c,d;
a=25,b=10,c=5,d=1;
printf("请输入找零的钱数!\n");
scanf("%d",&m);
int a1=m/25;//两角五分硬币的个数
int b1=(m%25)/10;//一角硬币的个数
int c1=((m%25)%10)/5;//五分硬币个数
int d1=(((m%25)%10)%5)/1;//一分硬币个数
printf("请输出结果\n");
printf("25分为%d个\n",a1);
printf("10分为%d个\n",b1);
printf("5分为%d个\n",c1);
printf("1分为%d个\n",d1);
}
但是,若存在7分钱,那么这个输出的就不一定是最优方案了。
至于为什么不是最优、如何解决,等我深入学习看看是否能得出答案