貪心問題的應用之點點滴滴二三事兒(摘自《算法設計與實踐》)

貪心的基本知識就不說了...比較基礎的

貪心算法的基本步驟:

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(這道題可以用貪心和樹狀數組來解,樹狀數組還沒有涉及,但是我會回來的......)

    HDU 2570 迷瘴 



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章