關於區間貪心的補全

2021-09-12 18:10:08 字數 1872 閱讀 4882

之前在部落格裡總結過貪心演算法的相關注意概念,但是由於當時理解不夠,並沒有很好的總結區間貪心問題,所以在這裡做乙個總結:

區間貪心演算法總的來說有兩大題型,乙個是區間不相交問題,乙個是區間選點問題;

其實第二種問題是第一種問題的子問題,並且對於貪心演算法中的概念一定要有所體會;

一、區間不相交

當出現這鐘情況的時候,我們應該優先選擇i1,因為這樣的話就可以給其他區間騰出很多的空閒位置;

其次,當消除了所有子區間重疊問題的時候,我們會有如下的情況出現:

對於這種情況,我們採用的是對各個區間按照左端點的大小進行排序,此時就會形成上圖的情況,每個區間的有右邊節點有序;

**如下所示:

#include#include#includeusing namespace std;

const int maxn=110;

struct intevali[maxn];

bool cmp(inteval a,inteval b){

if(a.x!=b.x)

return a.x>b.x;//左端從大到小進行排序

else

return a.y其實最難理解的應該是**中的處理,這裡給出詳細的解釋:

首先來看排序函式

bool cmp(inteval a,inteval b){

if(a.x!=b.x)

return a.x>b.x;//左端從大到小進行排序

else

return a.y這裡之所以要在左端大小相同的情況下對右端進行遞增排序,是為了找出包含區間中的最小的子區間;

這樣進行排序的時候,就會變成存在包含關係的區間在一起,但是首位肯定是包含區間中的最小區間;

之後就是主體處理;

while(scanf("%d",&n),n!=0){

for(int i=0;i這裡注意for迴圈,其實就是對陣列進行上述分析的第二部處理,從右向左,尋找不重合的區間(由於排序函式的操作,找到的必定是重合區間中的最小區間),迴圈從而使得每次選擇出來的都是最小的不重合的區間;

個人認為,區間不重疊的貪心思路主要體現在尋找最小的包含區間上;對於每一塊有重合情況的區間,我們只需要找出每一塊的重合區間中的最小區間,就可以組合成不重疊的區間,並且這些區間肯定數目最大,符合題意;

二、區間選點

區間選點可以視為第一種問題的衍生問題,目的是將給出開區間(注意,這裡是開區間)中選擇點,使得每個區間都至少有乙個點;

該問題也涉及重疊區間的問題。

還是一樣,當上述情況發生的時候,我們如果點放在i1內,就會使得i2內也存在點;所以根本上來說,我們還是尋找重疊區間內最小的區間;

因此,我們採用的還是第一類問題的操作,但是需要注意的就是點的選取;

對於有序的序列,我們應該把點選在左端點,而不是右端點;

關於這個問題,可以這樣想:

對於上述情況,如果選取右端點,就會出現選擇兩個的情況,但是如果選取左端點,就只用選取乙個;

所以,只需要對之前的**進行修改,修改乙個判定條件;

將i[i].y<=lastx

修改為i[i]即可

關於區間貪心的補全

之前在部落格裡總結過貪心演算法的相關注意概念,但是由於當時理解不夠,並沒有很好的總結區間貪心問題,所以在這裡做乙個總結 區間貪心演算法總的來說有兩大題型,乙個是區間不相交問題,乙個是區間選點問題 其實第二種問題是第一種問題的子問題,並且對於貪心演算法中的概念一定要有所體會 一 區間不相交 當出現這鐘...

關於區間貪心的補全

之前在部落格裡總結過貪心演算法的相關注意概念,但是由於當時理解不夠,並沒有很好的總結區間貪心問題,所以在這裡做乙個總結 區間貪心演算法總的來說有兩大題型,乙個是區間不相交問題,乙個是區間選點問題 其實第二種問題是第一種問題的子問題,並且對於貪心演算法中的概念一定要有所體會 一 區間不相交 當出現這鐘...

貪心 區間貪心

給出n個開區間 x,y 從中選擇盡可能多的開區間,使得這些開區間兩兩沒有交集。先對左端點 從大到小 排序,如果左端點相同就對右端點從小到大排序。區間不相交問題 include include using namespace std const int maxn 110 區間結構體 struct in...