Contents

区间调度算法

区间调度

1.最多区间调度问题

https://cdn.staticaly.com/gh/Hongtao-Xu/note@main/img/202208202254896.png

问题的目标是求不重叠的最多区间个数,贪心算法求解:在可选的工作中,每次都选取结束时间最早的工作

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
const int MAX_N=100000;  
//输入  
int N,S[MAX_N],T[MAX_N];  
  
//用于对工作排序的pair数组  
pair<int,int> itv[MAX_N];  
  
void solve()  
{  
    //对pair进行的是字典序比较,为了让结束时间早的工作排在前面,把T存入first,//把S存入second  
    for(int i=0;i<N;i++)  
    {  
        itv[i].first=T[i];  
        itv[i].second=S[i];  
    }  
  
    sort(itv,itv+N);  
  
    //t是最后所选工作的结束时间  
    int ans=0,t=0;  
    for(int i=0;i<N;i++)  
    {  
        if(t<itv[i].second)//判断区间是否重叠  
        {  
            ans++;  
            t=itv[i].first;  
        }  
    }  
  
    printf(%d\n,ans);  
}  

时间复杂度:O(nlogn)

2.最大区间调度

https://cdn.staticaly.com/gh/Hongtao-Xu/note@main/img/202208202303769.png

不重叠的累加区间长度,动态规划算法:按照结束时间排序区间,然后按照第i个区间选择与否进行动态规划

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
const int MAX_N=100000;  
//输入  
int N,S[MAX_N],T[MAX_N];  
  
//用于对工作排序的pair数组  
pair<int,int> itv[MAX_N];  
  
void solve()  
{  
    //对pair进行的是字典序比较,为了让结束时间早的工作排在前面,把T存入first,//把S存入second  
    for(int i=0;i<N;i++)  
    {  
        itv[i].first=T[i];  
        itv[i].second=S[i];  
    }  
  
    sort(itv,itv+N);  
  
    dp[0] = itv[0].first-itv[0].second;  
    for (int i = 1; i < N; i++)  
    {  
        int max;  
  
        //select the ith interval  
        int nonOverlap = lower_bound(itv, itv[i].second)-1;  
        if (nonOverlap >= 0)  
            max = dp[nonOverlap] + (itv[i].first-itv[i].second);  
        else  
            max = itv[i].first-itv[i].second;  
  
        //do not select the ith interval  
        dp[i] = max>dp[i-1]?max:dp[i-1];  
    }  
    printf(%d\n,dp[N-1]);  
}  

3.带权区间调度

在每个区间上绑定一个权重,求加权之后的区间长度最大值

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
const int MAX_N=100000;  
//输入  
int N,S[MAX_N],T[MAX_N];  
  
//用于对工作排序的pair数组  
pair<int,int> itv[MAX_N];  
  
void solve()  
{  
    //对pair进行的是字典序比较,为了让结束时间早的工作排在前面,把T存入first,//把S存入second  
    for(int i=0;i<N;i++)  
    {  
        itv[i].first=T[i];  
        itv[i].second=S[i];  
    }  
  
    sort(itv,itv+N);  
  
    dp[0] = (itv[0].first-itv[0].second)*V[0];  
    for (int i = 1; i < N; i++)  
    {  
        int max;  
  
        //select the ith interval  
        int nonOverlap = lower_bound(itv, itv[i].second)-1;  
        if (nonOverlap >= 0)  
            max = dp[nonOverlap] + (itv[i].first-itv[i].second)*V[i];  
        else  
            max = (itv[i].first-itv[i].second)*V[i];  
  
        //do not select the ith interval  
        dp[i] = max>dp[i-1]?max:dp[i-1];  
    }  
    printf(%d\n,dp[N-1]);  
}  

带权区间调度应用最广,最大区间调度其次,最多区间调度应用范围最小。从通用的DP到特殊的DP再到贪心算法,难度逐渐降低。下图展示了三个问题的关系:

image-20220820230754322