貪心演算法 區間問題

2021-09-16 22:31:21 字數 4463 閱讀 6054

區間選單個點

問題描述:

數軸上有n個閉區間[ai, bi]。取盡量少的點,使得每個區間內都至少有乙個點(不同區間內含的點可以是同乙個)。

輸入

第1行:乙個整數n

接下來n行,每行2個整數ai,bi

輸出

乙個整數,表示滿足條件的最少點數。

樣例輸入

5

4 62 3

1 46 8

5 7

【樣例輸出】

2
策略分析:

題目要求每個區間都至少有乙個點,那麼如果存在區間重疊的區域,我們肯定要把點放在重疊的區間最多的區域,同時如果存在小區間包含在大區間中,我們只需要滿足小區間即可,同時,每一次選擇點的時候,一定是選擇該區間的右端點,這樣這個點才可能在覆蓋當前區間的情況下盡可能的覆蓋最多的區間。

因此1、按照每乙個區間的右端點從小到大排序

2、每一次判斷當前區間的左端點是否和上乙個區間右端點相交,如果相交記錄一次,否則要記錄兩次

注意:每次記錄的時候,預設選擇區間的右端點

**

#include 

#include

#define maxn 100000+10

using namespace std;

struct nodea[maxn]

;bool cmp

(node x, node y)

intmain()

printf

("%d\n"

, cnt)

;return0;

}

種樹問題(選點)

問題描述:

一條街的一邊有幾座房子。因為環保原因居民想要在路邊種些樹。路邊的地區被分割成塊,並被編號為1…n。每個塊大小為乙個單位尺寸並最多可種一棵樹。每個居民想在門前種些樹並指定了三個號碼b,e,t。這三個數表示該居民想在b和e之間最少種t棵樹。當然b <= e,居民必須保證在指定地區不能種多於地區被分割成塊數的樹,即要求t <= e-b+1。允許居民想種樹的各自區域可以交叉。出於資金短缺的原因,環保部門請你求出能夠滿足所有居民的要求,需要種樹的最少數量。

輸入

共n+1行

第1行:輸入乙個n,表示有n戶居民提出要求要在門前種樹(1 ≤ n ≤ 100)

後n行:每行輸入3個數bi、ei和ti,用空格隔開,分別表示第i戶居民想在門前的起點bi到終點ei(包括端點),想種ti顆樹(1 ≤ bi ≤ ei ≤100)

輸出

滿足n戶居民的最少種樹量

樣例輸入

4

1 4 2

4 6 2

8 9 2

3 5 2

【樣例輸出】

5
策略分析:

同樣是選點問題,不過變成了選多個點,同樣按右端點排序,然後每次種樹都從右往左種樹,種樹之前先掃瞄這個區間已經種了多少樹,然後再種剩下需要種的,使用乙個bool陣列記錄當前的點是否種了樹

#include 

#include

#define maxn 105

bool used[maxn]

;struct zonea[maxn]

;bool cmp

(zone x, zone y)

int n, cnt;

intmain()

}printf

("%d\n"

, cnt)

;return0;

}

問題描述:

數軸上有n個開區間(ai, bi)。選擇盡量多個區間,使得這些區間兩兩沒有公共點。

輸入

n+1行

第一行:n,表示區間的數量

接下來n行:每行兩個數,表示這個區間的起始點和終止點

輸出

乙個數,最大不相交區間

樣例輸入

11

3 51 4

3 85 7

1 66 10

8 12

8 11

12 14

2 13

5 9

樣例輸出

4
策略分析:

首先假設有兩個區間x和y,如果x包含在y中,那麼我們選擇區間時,應該選擇x,因為選擇x會留下更多的剩餘的空間去選擇其他的區間

然後按照區間右端點排序,同樣定義乙個變數設定為當前區間的右端點,每次選擇下乙個區間的左端點大於當前右端點的區間,更新當前端點即可(由於是按照右端點排序的,那麼每次選擇下乙個區間的時候,右端點都在變大,因此我找到下乙個區間左端點大於當前右端點即可更新,這樣更新出來的留下來的空間才是最大的)

**

#include 

#include

#define maxn 55

struct nodea[maxn];

bool cmp

(node x, node y)

intmain()

std:

:sort

(a+1

, a+

1+n, cmp)

; now = a[1]

.end;

for(

int i =

2; i <= n; i++)}

printf

("%d\n"

, sum)

;return0;

}

問題描述:

數軸上有n個閉區間[ai,bi]。選擇盡量少的區間覆蓋一條指定線段[s,t]

輸入

n+1行

第一行:乙個整數n,表示n個區間,然後是s和t

接下來n行:每行兩個整數,表示每個區間的起點和終點

輸出

表示最少需要的區間數,如果無解輸出no answer

樣例輸入

8 1 10

-3 -1

13 16

0 32 6

3 56 10

5 64 10

樣例輸出

3
策略分析:

區間問題無非就是對區間進行處理,排序篩選,對於區間覆蓋來說,要求選擇最少的區間數

1、那麼首先應該想到,在可能的情況下,應該選擇覆蓋長度盡可能長的區間,所以如果存在區間包含的情況,應該選擇長的區間。

2、在讀入時可以對每乙個區間進行預處理,幫助做更好的判斷,如果讀入的區間不在[s,t]範圍內,捨去這個無用區間,同時小於s的部分和大於t的部分也要捨去

3、按照左端點從小大大排序(因為要求覆蓋,所有應該從左邊開始),如果中間有斷層或者第乙個端點不是s都是無解的情況

**

#include 

#include

#define maxn 1000005

using namespace std;

struct node a[maxn]

;bool cmp

(node x, node y)

intmain()

}sort

(a+1

, a+

1+k, cmp);if

(a[1

].l > s)

now = a[1]

.r; i =1;

while

(now < t && i <= k)

temp = now;

for(

int j = i+

1; j <= k; j++)}

if(temp == now && temp < t)

i = loc;

now = temp;

cnt++;}

printf

("%d\n"

, cnt)

;return0;

}

區間排程問題 貪心演算法

問題 有 n 項工作,每項工作分別在 s i 時間開始,在 t i 時間結束 對於每項 工作,你都有可以選擇參與與否。如果選擇了參與,那麼自始自終都必須全程參與。此外,參與工作的時間段不能重疊 即使是開始的瞬間和結束的瞬間的重疊也 是不允許的 include include include usin...

貪心演算法 區間找點問題

找點 時間限制 2000 ms 記憶體限制 65535 kb 難度 2 描述 上數學課時,老師給了lyh一些閉區間,讓他取盡量少的點,使得每個閉區間內至少有乙個點。但是這幾天lyh太忙了,你們幫幫他嗎?輸入 多組測試資料。每組資料先輸入乙個n,表示有n個閉區間 n 100 接下來n行,每行輸入兩個數...

區間排程問題 貪心演算法

一 題目 區間排程問題 有n項工作,每項工作分別在si時間開始,在ti時間結束。對於每項工作,你都可以選擇參與與否。如果選擇了參與,那麼自始至終都必須全程參與。此外,參與工作的時間段不能重複 即使是開始的瞬間和結束的瞬間的重疊也是不允許的 你的目標是參與盡可能多的工作,那麼最多能參與多少項工作呢?1...