參考:《算法導論》第16章
貪心算法:在對問題求解時,總是做出在目前看來是最好的選擇。
貪心算法的基本思路:
1.建立數學模型來描述問題。
2.把求解的問題分成若幹個子問題。
3.對每一子問題求解,得到子問題的局部最優解。
4.把子問題的解局部最優解合成原來解問題的一個解。
活動選擇問題:貪心算法最經典的例子:給出n個任務和每個任務的開始和結束時間,找出可以完成的任務的最大數量,在同一時刻隻能做一個任務。
先把活動按照結束時間的單調遞增順序排序,最早結束的活動總是最優解的一部分。
#include <iostream>
using namespace std;
void GreedyChoose(int len,int *s,int *f,bool *flag)
{
flag[0] = true;
int j = 0;
for(int i=1;i<len;++i)
{
if(s[i] >= f[j]) //前一個活動的結束時間早于後一個活動的開始時間
{
flag[i] = true;
j = i;
}
}
}
int main()
{
int s[11] ={1,3,0,5,3,5,6,8,8,2,12}; //開始時間
int f[11] ={4,5,6,7,8,9,10,11,12,13,14}; //結束時間
bool mark[11] = {false}; //标記
GreedyChoose(11,s,f,mark); //貪心算法
for(int i=0;i<11;i++) //輸出結果
if(mark[i])
cout<<i<<" ";
return 0;
}
線段覆寫:在一維空間中告訴你N條線段的起始坐标與終止坐标,要求求出這些線段一共覆寫了多大的長度。
#include <iostream>
using namespace std;
int main()
{
int s[10] = {2,3,4,5,6,7,8,9,10,11};
int f[10] = {3,5,7,6,9,8,12,10,13,15};
int TotalLength = (3-2);
for(int i=1,j=0; i<10 ; ++i)
{
if(s[i] >= f[j])
{
TotalLength += (f[i]-s[i]);
j = i;
}
else
{
if(f[i] <= f[j])
continue;
else
{
TotalLength += f[i] - f[j];
j = i;
}
}
}
cout<<TotalLength<<endl;
return 0;
}