贪心的基本知识就不说了...比较基础的
贪心算法的基本步骤:
1、从问题的某个初始解出发。
2、采用循环语句,当可以向求解目标前进一步时,就根据局部最优策略,得到一个部分解,缩小问题的范围或者规模。
贪心算法应用于:
1、引导问题。最基本的就是HDU 1009 FatMouse' Trade(水题小能手hhhhh)。
2、时间序列问题。(觉得其实就是活动安排问题。)
具体解释下:
已知N个事件的发生时刻和结束时刻(事件已经按照结束时刻升序排序)。一些在时间上没有重叠的事件,可以构成一个事件序列。
事件序列包含的时间数目,称为该事件序列的长度。
试找出一个最长的事件序列。
分析:
不妨用Begin[I]和End[I]表示事件I的开始时刻和结束时刻,则原题的要求就是找一个最长的序列a1 < a2 < ...... < an,满足:
Begin[a1] < End[a1] <= ...... <= Begin[an] < End[an].
可以证明,如果在可能的事件a1 < a2 < a3 < ...... < an中选取时间上不重叠的最长序列,那么一定存在一个包含a1(结束最早)的最长序列。
根据这种题,书上给出的样题是:HDU 2037 今年暑假不AC
呃......其实某破航也给出了一道题:忙碌的Nova君
<两道题的解法几乎相同......>
给出某官方的代码【注意对上一个时间的记录和处理。】(逃
#include<iostream>
#include<cstdlib>
#include<algorithm>
using namespace std;
struct inp
{
int x,y;
}node[105];
bool cmp(inp a, inp b)
{
return a.y < b.y;
}
int main(){
int i,j,s,n;
while(scanf("%d", &n) && n)
{
for(i = 0; i < n; i++)
cin >> node[i].x >> node[i].y;
sort(node, node + n, cmp);
j = 0;
s = 1;
for(i = 0; i < n; i++)
{
if(node[i].x >= node[j].y)
{
s++;
j = i;
}
}
printf("%d\n", s);
}
return 0;
}
3、区间覆盖问题。
具体描述:
用i表示x轴上坐标为[ i - 1, i ]的区间(长度为1),并给出M(1 <= M <= 200) 个不同的整数,表示M个这样的区间。
现在让你画几条线段覆盖住所有的区间,条件是每一条线段可以任意长,但是要求所画线段之和最小,并且线段的数目不超过N。
分析:
如果N>= M,那么显然用M条长度为1 的线段可以覆盖住所有的区间,所求的线段总长为M。
如果N = 1,那么显然所需的线段总长为i(max) - i(min) + 1。
如果N = 2,那么相当于是在N = 1的情况下从某一个地方断开。
如果N = k,那么从间隔最大的两个部分断开。
给出书本上面的样题:HDU 1051 Wooden Sticks(需要使用到标记值,颇费脑子)
HDU 1050 Moving Tables(这道题可以用贪心和树状数组来解,树状数组还没有涉及,但是我会回来的......)