C++ Knowledge Lecture 15 | Three types of interval coverage problems based on greedy thinking [Detailed explanation of supporting resources]

 

Blogger homepage: Yu·Xiansheng

Supporting resources: Three types of coverage problems based on greedy algorithms-C++ document resources-CSDN download

Column: C++ knowledge in depth

Table of contents

Three types of interval coverage problems based on greedy thinking

Scenario 1: Complete interval coverage problem

describe:

Example:

Problem solving process:

example:

Question meaning:

example:

Example two:

Idea:

Scenario 2: The problem of the maximum number of disjoint intervals

example:

Input format:

Output format:

Idea:

Scenario 3: Interval point selection problem.

describe

enter

output

Sample input

Sample output

Exercise: POJ 3485 Highway

main idea:

Sample Input

Sample Output

Idea:


Three types of interval coverage problems based on greedy thinking

Scenario 1: Complete interval coverage problem

describe:

Given an interval of length m, and then given the starting point and end point of n line segments (note that this is a closed interval), find the minimum number of line segments that can completely cover the entire interval.

Example:

Interval length 8, optional coverage line segments [2,6],[1,4],[3,6],[3,7],[6,8],[2,4],[3,5]

Problem solving process:

1 Arrange each interval in increasing order of the left endpoint. After the order is completed, it is [1,4], [2,4], [2,6], [3,5], [3,6], [3, 7],[6,8]

2Set a variable to represent the area that has been covered. Among the remaining line segments, find all the line segments whose left endpoint is less than or equal to the right endpoint of the currently covered area. The line segment with the largest right endpoint is added until the entire area is covered.

3 process:

Assuming that [1,4] is added in the first step, then the options that can be selected in the next step are [2,6], [3,5], [3,6], [3,7]. Since 7 is the largest, the next step is to choose [3,7], you can only choose [6,8] in the last step. At this time, you just reach 8 and exit, and the selected interval is 3

4. Greedy proof:

A minimum number of line segments are required for coverage, so the selected line segment must be as long as possible, and the place before the area that has been covered does not matter (it can be understood that all the left end points that can be covered are the places that have been covered), then What can really change the line segment is the right endpoint. The left endpoint does not have much meaning, so select the right endpoint to cover it.

example:

Intervals(http://poj.org/problem?id=1089

Description

There is given the series of n closed intervals [ai; bi], where i=1,2,...,n. The sum of those intervals may be represented as a sum of closed pairwise non−intersecting intervals. The task is to find such representation with the minimal number of intervals. The intervals of this representation should be written in the output file in acceding order. We say that the intervals [a; b] and [c; d] are in ascending order if, and only if a <= b < c <= d.

Task

Write a program which:

reads from the std input the description of the series of intervals,

computes pairwise non−intersecting intervals satisfying the conditions given above,

writes the computed intervals in ascending order into std output

Input

In the first line of input there is one integer n, 3 <= n <= 50000. This is the number of intervals. In the (i+1)−st line, 1 <= i <= n, there is a description of the interval [ai; bi] in the form of two integers ai and bi separated by a single space, which are respectively the beginning and the end of the interval,1 <= ai <= bi <= 1000000.

Output

The output should contain descriptions of all computed pairwise non−intersecting intervals. In each line should be written a description of one interval. It should be composed of two integers, separated by a single space, the beginning and the end of the interval respectively. The intervals should be written into the output in ascending order.

Sample Input

5

5 6

1 4

10 10

6 9

8 10

Sample Output

1 4

5 10

Question meaning:

Find the maximum coverage of the interval

#include <iostream>

#include <vector>

#include <algorithm>

#include <cstring>

#include <cstdio>

#include <cmath>

using namespace std;

const int maxn=50000+20;

struct area{

int l,r;

}a[maxn];

int cmp(area x,area y){

if(x.l==y.l)return x.r<y.r;

return x.l<y.l;

}

int main(){

int ans,la,lb,n,i;

scanf("%d",&n);

for(i=1;i<=n;i++){

scanf("%d%d",&a[i].l,&a[i].r);

if(a[i].l>a[i].r)swap(a[i].l,a[i].r);

}

sort(a+1,a+n+1,cmp);

la=a[1].l;lb=a[1].r;

for(i=2;i<=n;i++){

if(a[i].l>lb){

printf("%d %d\n",la,lb);

la=a[i].l;lb=a[i].r;

}

else {

lb=max(lb,a[i].r);

}

}

printf("%d %d\n",la,lb);

return 0;

}

example:

[NOIP2005 Popularization Group] The tree outside the school gate-Luogu

#include<bits/stdc++.h>

using namespace std;

const int maxn=100+20;

struct area{

int l,r;

}a[maxn];

int cmp(area x,area y){

if(x.l==y.l)return x.r<y.r;

return x.l<y.l;

}

int main(){

int ans,la,lb,n,i,L;

scanf("%d%d",&L,&n);

for(i=1;i<=n;i++){

scanf("%d%d",&a[i].l,&a[i].r);

if(a[i].l>a[i].r)swap(a[i].l,a[i].r);

}

sort(a+1,a+n+1,cmp);

ans=L+1;la=a[1].l;lb=a[1].r;

for(i=2;i<=n;i++){

if(a[i].l>lb){

ans-=lb-la+1;

la=a[i].l;lb=a[i].r;

}

else {

lb=max(lb,a[i].r);

}

}

ans-=lb-la+1;

cout<<ans<<endl;

return 0;

}

Example two:

Idea:

For each input point, first use the Pythagorean theorem to find the starting point and end point that can cover the rectangle, and then perform a sorting. If the minimum starting point and the maximum end point cannot exceed the length range of the rectangle, there must be no solution. Take out The most forward point of the starting point, then record the end point of this point, traverse all other points within the range from the starting point to the end point, and select the point at the back of the end point as the position of the next end point, and add one to the counter , continue to traverse backwards, if there is an area that cannot be connected, it means that there is no solution. If it successfully traverses to the end of the rectangle, it will directly output the value of the counter.

#include<cstdio>

#include<cstdlib>

#include<iostream>

#include<algorithm>

using namespace std;

const int maxn=10000+10;

struct area{

double l,r;

}a[maxn];

int cmp(area x,area y){

if(x.l==y.l)return x.r<y.r;

else return x.l<y.l;

}

int main(){

int t,n,w,flag,i,tot,x,ans,pos;

double h,tmp,lb,r;

scanf("%d",&t);

while(t--){

scanf("%d%d%lf",&n,&w,&h);

h=h/2;//矩形的高

tot=0;//共tot个矩形覆盖

for(i=1;i<=n;i++){

scanf("%d%lf",&x,&r);

tmp=sqrt(r*r-h*h);//计算矩形的宽

if(tmp>0){

a[++tot].l=max(0.0,x*1.0-tmp);

a[tot].r=x*1.0+tmp;

}

}

sort(a+1,a+tot+1,cmp);

ans=0;

flag=1;

pos=1;

lb=0;//前pos个区间能覆盖的最大区间

for(;lb<w;){

tmp=0;

for(i=pos;a[i].l<=lb&&i<=tot;i++){

tmp=max(tmp,a[i].r);//左边界在lb以内能覆盖到的最远距离

}

if(tmp>lb){

ans++;//增加一个喷头

lb=tmp;//更新lb

pos=i;//更新pos

}

else {//无法往后覆盖

flag=0;

break;

}

}

if(flag)printf("%d\n",ans);else printf("0\n");

}

return 0;

}

Scenario 2: The problem of the maximum number of disjoint intervals

There are n intervals [ai,bi] on the number axis, and it is required to select as many intervals as possible, so that these intervals have no common points.

Greedy strategy:

Sort according to b1<=b2<=b3..., and then traverse from front to back, whenever you encounter a range that can be added to the set, add it to the set. (A set represents a collection of solutions)

prove:

We consider the relationship between a1, a2... in the following situations:

1. a1>a2. At this time, interval 2 includes interval 1. In this case, interval 2 is obviously not selected, because selecting interval 1 will leave more free space.

This is not only the case for interval 2, as long as there is one i in all intervals that satisfies a1 > ai, do not choose i.

That is to say, in this case, it is wise to choose interval 1, which is consistent with the strategy.

2. After excluding case 1, there must be a1<=a2<=a3…….

example:

Line segment coverage

It is known that there are 0<N<10000 line segments on the number axis. Each line segment is defined according to the endpoints Ai and Bi (Ai<>Bi,i=1..N). The endpoint coordinates are within (-999, 999), and the coordinates are integers. Some line segments may intersect. Programming to delete the minimum number of line segments so that any two remaining line segments do not intersect.

Input and output format

Input format:

The first line is an integer N. Next there are N lines, each line contains two integers (Ai and Bi), separated by spaces.

Output format:

The integer p is the number of line segments remaining after deletion.

Input and output samples

Input example #1:

3

6 3

1 3

2 5

Output sample #1:

2

Idea:

Greedy thinking, time complexity O(nlog(n))

1. The endpoints given by the data may be in reverse order and need to be judged and processed.

2. Sort, arrange each interval in increasing order according to the right endpoint

3. The first interval must be retained. The maximum right boundary of the record retention interval is pos. Traverse the interval i. If a[i].l>pos, the retainable interval increases and pos is updated to a[i].r. .

#include<bits/stdc++.h>

#define MaxInt 100000

using namespace std;

const int maxn=10000+20;

struct line{

int l,r;

}a[maxn];

int n;

int cmp(line x,line y){return x.r<y.r;}

int main(){

int i;

scanf("%d",&n);

for(i=1;i<=n;i++){

scanf("%d%d",&a[i].l,&a[i].r);

if(a[i].l>a[i].r)swap(a[i].l,a[i].r);

}

sort(a+1,a+n+1,cmp);

int ans=1,pos=a[1].r;

for(i=2;i<=n;i++)

if(a[i].l>=pos){

ans++;

pos=a[i].r;

}

printf("%d",ans);

return 0;

}

Scenario 3: Interval point selection problem.

There are n closed intervals [ai, bi] on the number axis. Take as few points as possible, so that there is at least one point in each interval (the points contained in different intervals can be the same).

Greedy thoughts:

First sort by b from small to large, and then select b0 as the selected point pos. If ai>pos appears, use bi as pos, and then iterate in this way. Until all intervals are traversed.

describe

In math class, the teacher gave LYH some closed intervals and asked him to take as few points as possible so that there is at least one point in each closed interval. But LYH is too busy these days, can you help him?

enter

Multiple sets of test data.

Enter an N for each set of data, indicating that there are N closed intervals (N≤100).

In the next N lines, enter two numbers a, b (0≤a≤b≤100) in each line, indicating the two endpoints of the interval.

output

Output an integer, indicating the minimum number of points that need to be found.

Sample input

4

1 5

2 4

1 4

2 3

3

1 2

3 4

5 6

1

2 2

Sample output

1

3

1

#include<cstdio>

#include<cstdlib>

#include<iostream>

#include<algorithm>

using namespace std;

const int maxn=100+10;

struct area{

int l,r;

}a[maxn];

int cmp(area x,area y){

if(x.r==y.r)return x.l<y.l;

else return x.r<y.r;

}

int main(){

int n,i,pos,ans;

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

for(i=1;i<=n;i++)

scanf("%d%d",&a[i].l,&a[i].r);

sort(a+1,a+n+1,cmp);

ans=1;pos=a[1].r;

for(i=2;i<=n;i++){

if(a[i].l>pos){

ans++;

pos=a[i].r;

}

}

printf("%d\n",ans);

}

return 0;

}

Exercise: POJ 3485 Highway

main idea:

The road on the X-axis goes from 0 to L. There are some points above and below the X-axis that give coordinates to represent villages. How many exits should be built on the highway so that the distance from each village to the exit does not exceed D.

Sample Input

100

50

3

2 4

50 10

70 30

Sample Output

1

1

Idea:

Taking the coordinates of each village as the center of the circle and D as the radius, draw a circle with two intersection points with the X-axis to obtain an interval. After obtaining N intervals, it is transformed into an interval point selection problem. The strategy is: first sort by the right endpoint of the interval from small to large, and if they are the same, sort by the left endpoint from large to small.
 

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <cmath>
#include <algorithm>
using namespace std;
struct point
{
    double left;
    double right;
}po[100000];
int cmp(const void *a,const void *b)
{
    return (*(point*)a).right < (*(point*)b).right ? -1 : 1;
}
int main()
{
    double way_long,dis;
    int n,i,j,k;
    double a,b;
    double rec;
    int re;
    while(scanf("%lf%lf%d",&way_long,&dis,&n)!=EOF)
    {
        re=0;
        for(i=0;i<n;i++)
        {
        scanf("%lf%lf",&a,&b);
        rec=sqrt(dis*dis-b*b);
        po[i].left=a-rec;
        po[i].right=a+rec;
        if(po[i].left < 0)
        po[i].left=0;
        }
        qsort(po,n,sizeof(po[0]),cmp);
       // for(i=0;i<n;i++)
        //printf("%lf\n",po[i].right);
        re=0;
        i=0;
        while(i<n)
        {
            k=i;
            re++;
            while(i<n && po[i].left <= po[k].right) i++;
        }
        printf("%d\n",re);
    }
    return 0;
}

Guess you like

Origin blog.csdn.net/djfihhfs/article/details/127638478
Recommended