基本思想
- 贪心算法总是作出在当前看来最好的选择。也就是说贪心算法并不从整体最优考虑,它所作出的选择只是在某种意义上的局部最优选择。虽然贪心算法不能对所有问题都得到整体最优解,但对许多问题它能产生整体最优解。
- 动态规划算法通常以自底向上的方式解各子问题,而贪心算法则通常以自顶向下的方式进行,以迭代的方式作出相继的贪心选择,每作一次贪心选择就将所求问题简化为规模更小的子问题
- 对于一个具体问题,要确定它是否具有贪心选择性质,必须证明每一步所作的贪心选择最终导致问题的整体最优解。
- 当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性质。问题的最优子结构性质是该问题可用动态规划算法或贪心算法求解的关键特征。
例题:
活动安排问题:
设有n个活动的集合E={1, 2, ..., n},其中,每个活动都要求使用同一资源,如演讲会场等,而在同一时间内只有一个活动能使用这一资源。每个活动i 都有一个要求使用该资源的起始时间 si 和一个结束时间 fi ,且si < fi。
思路:在当前活动找下一个最早结束时间且相容的活动,这样总能剩下最多时间来安排更多的活动。
#include<stdio.h>
struct la
{
int st,end;//st是开始时间 end是结束时间
} a[10000],k;
int main()
{
int n,i,j,b=1;
scanf("%d",&n);
for(i=0; i<n; i++)
cin>>a[i].st>>a[i].end;
for(i=0; i<n-1; i++)
for(j=0; j<n-1-i; j++)
if(a[j+1].end<a[j].end)
{
k=a[j+1];
a[j+1]=a[j];
a[j]=k;
}
j=0;
for(i=1; i<n; i++)
if(a[j].end<=a[i].st)
b++,j=i;
cout<<b;
}
背包问题:
与0-1背包相似但是可以将物品分割开只装一部分
思路:可以装的空间是一定的,单位重量越值钱越装,也就是说装性价比高的
#include<iostream>
#include<algorithm>
using namespace std;
// 装性价比高的
struct iteam
{
double wight;
double value;
double xjb;
};
bool cmp(iteam a, iteam b)
{
return a.xjb>b.xjb;
}
double knapbag(int n,iteam a[],double c)// n物品个数 c背包容量
{
int i=0;
int k=0;
double pvalue=0;
sort(a,a+n,cmp);
while(i<n&&k<c)
{
pvalue+=a[i].wight*a[i].xjb;
k+=a[i].wight;
i++;
}
if(i<n)
{
double kk=c-k;
pvalue+=kk*a[i].xjb;
}
return pvalue;
}
int main()
{
int n,kk;
cin>>n>>kk;
iteam a[n];
for(int i=0;i<n;i++)
{
cin>>a[i].wight>>a[i].value;
a[i].xjb=a[i].wight/a[i].value;
}
double abb=0;
abb=knapbag(n,a[n],kk);
cout<<abb;
}