贪心法
贪心法常用于解决最优化问题,但与动态规划不同的是,贪心法不是从整体考虑最优,而是考虑选择在某种意义的局部最优。例如为了让找的零钱的纸币数量最少,每次我们会去尽量用面值最大的纸币取找。
贪心算法不能保证得到最优解,用贪心法能够得到最优解得问题有两个特质:1、一个问题得最优解包含其子问题得最优解。2、问题整体最优解可以通过一系列局部最优解得选择得到。
活动选择问题
给出n个活动的开始时间和结束时间,从中选择任意活动,要求同一时间只能选择一个活动,找出可参与最多活动数。
算法分析:活动ai的活动时间为区间[si, fi),活动选择问题九四要选择出一个由互不影响的活动组成的最大子集合。由于该问题具有最优子结构和贪心选择选择,所以可以使用贪心策略来解决。
算法策略有三种:1、选择活动时,每次选取结束时间最早的活动 2、每次选择活动持续时间最少的活动 3、每次选择最早开始的活动
由于2、3算法都无法得到最优解,所以选择1算法(选择活动时,每次选取结束时间最早的活动)最合适
class Solution{
int Selectactivities(int n, vector<int> s, vector<int> f)
{
//用于对活动排序的pair数组
vector<pair<int, int>> itv;
for(int i=0;i<n;i++)
{
itv[i].second = s[i];
itv[i].first = f[i];//为了对结束时间排序
}
sort(itv, itv+n);//对pair进行排序,让结束时间早的活动排在前面
int ans = 0, t = 0;//ans表示选取活动的数量、t表示最后结束的时间
for(int i=0;i<n;i++)
{
if(t<itv[i].second)//上一次活动结束时间小于这次活动开始时间,可选
{
ans++;
t = itv[i].first;//结束时间
}
}
return ans;
}
}
背包问题
背包问题和01背包问题不同。在01背包问题中每个物品要么选要么不选,即只有0和1;而在背包问题,每个物品可以部分装入背包中,例如三斤糖可以选择一斤
算法策略:1、按最大价值先放背包的原则 2、按最小重量先放入背包的原则 3、按最大单位重量价值先放入背包的原则
可以证明算法3能够得到最优解
class Solution{
int GreedyKnaspsack(int n, int weight, vector<int> V, vector<int> W)
{
int values = 0;
vector<pair<double, int>> x;
for(int i=0;i<n;i++)
{
x[i].first = V[i]/W[i];//保存每件物品单位重量的价值
x[i].second = W[i];//保存物品质量
}
sort(x, x+n);
for(int i=n-1;i>=0;i--)
{
if(x[i].second<=W)//如果背包剩余容量可以装下该物品
{
values += x[i].second*x[i].first;
weights -= x[i].second;
}
else
break;
}
if(i>=0)
{
values += weights*x[i].first;//如果还有物品可以部分装入背包
}
return values;
}
}