贪心算法依然是分析局部,不同于分治所研究的小问题,这些局部问题与整体问题并不是同结构的。如果局部最优解能带来整体最优解,那贪心算法就是可用于解决问题的。
使用步骤:
1.分析局部问题。
2.看是否局部最优解能带来整体最优解。
3.如果是,则使用贪心算法。
P1. 以洛谷P1080国王游戏为例(贪心和排序思路,未AC)
分析局部问题。可以考察两个相邻的大臣情况。分别设为l1,r1,l2,r2代表相应左右手的数。设前面若干人乘积为a。
则大臣1在大臣2前面情形时,两者最大值为:
若大臣2在大臣1前面,两者最大值为:
通过很简单的数学推导可以知道,当第二种情形最大值大于第一种情形最大值时,会得到:
意味着,如果按照l*r作为标准,大臣呈非减序列排列,就可以出现最大值最小的情况。
否则,一定存在相邻的两个大臣l1,r1,l2,r2,其中,而大臣2在大臣1前面,则必然可以有大臣1在大臣2前面时最大值更小。也就是全局并非最优情况。
于是这样的局部最优解推出全局最优解的情况,可以采用贪心算法。
#include<iostream>
#include<algorithm>
#include<vector>
#include<cstdlib>
#include<string>
using namespace std;
struct minister
{
int left;
int right;
};
bool comparebymulti(minister &a,minister &b)
{
return a.left*a.right<b.left*b.right?1:0;
}
void showcurqueue(vector<minister> a)
{
for(int i=0;i<a.size();i++)
printf("%d %d\n",a[i].left,a[i].right);
}
int main()
{
int n;int kingleft,kingright;
cin>>n>>kingleft>>kingright;
vector<minister>ministers;
for(int i=0;i<n;i++)
{
int leftp,rightp;minister p;
cin>>leftp>>rightp;
p.left=leftp;p.right=rightp;
ministers.push_back(p);
}
sort(ministers.begin(),ministers.end(),comparebymulti);
showcurqueue(ministers);
return 0;
}