最长重叠线段或区间

题目:

X轴上有N条线段,每条线段包括1个起点和终点。线段的重叠是这样来算的,[10 20]和[12 25]的重叠部分为[12 20]。

给出N条线段的起点和终点,从中选出2条线段,这两条线段的重叠部分是最长的。输出这个最长的距离。如果没有重叠,输出0。

 

思路:

1、暴力计算

依次计算两两线段之间的重叠长度,但复杂度太高   (ps:可能我的第一反应就是暴力计算,以后多想想)

2、动态规划

假设S[n]表示n条线段中最长重叠距离,最长重叠距离只与两条线段有关,那么考虑两种情况:

1. 最长重叠距离与第n条线段无关,则最长重叠距离存在于前n-1条线段中,即S[n]=S[n-1];

2. 最长重叠距离与第n条线段有关,则最长重叠距离为第n条线段与前面n-1条线段中的最大重叠距离者,S[n]=max(overlap(segment[n],segment[i])), i=1....n-1

因此得到状态转移方程:

S[n]=0; n<=1

S[2]=overlap(segment[0],segment[1])

S[n]=max(S[n-1],max(overlap(segment[n],segment[i])))          for   i  in  0---n-1

代码:

动态规划:

/*
X轴上有N条线段,每条线段包括1个起点和终点。线段的重叠是这样来算的,[10 20]和[12 25]的重叠部分为[12 20]。

给出N条线段的起点和终点,从中选出2条线段,这两条线段的重叠部分是最长的。输出这个最长的距离。如果没有重叠,输出0。
*/
/*
*思路:假设S[n]表示n条线段中最长重叠距离,最长重叠距离只与两条线段有关,那么考虑两种情况:

1. 最长重叠距离与第n条线段无关,则最长重叠距离存在于前n-1条线段中,即S[n]=S[n-1];

2. 最长重叠距离与第n条线段有关,则最长重叠距离为第n条线段与前面n-1条线段中的最大重叠距离者,S[n]=max(overlap(segment[n],segment[i])), i=1....n-1

因此得到状态转移方程:

S[n]=0; n<=1

S[2]=overlap(segment[0],segment[1])

S[n]=max(S[n-1],max(overlap(segment[n],segment[i])))          for   i  in  0---n-1
*/
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
typedef struct {
	int start;
	int end;
}segment;
void displayOne(const segment &s1)
{
	cout << "[" << s1.start << "," << s1.end << "]  ";
}
void displayAll(const vector<segment>segs) {
	for (int i = 0; i < segs.size(); i++)
		displayOne(segs[i]);
	cout << endl;
}
bool isShorter(const segment &s1, const segment &s2);
int commonSegment(const segment &seg_a, const segment &seg_b);
int findLongestSegment(const vector <segment> &segments, int size);
int main()
{
	int n, start, end;
	cout << "please input the numbers: ";
	while (cin >> n)
	{
		vector<segment>segments(n);
		for (int i = 0; i < n; i++)
		{
			start = rand() % 30;
			end = start + rand() % 30;
			segments[i].start = start;
			segments[i].end = end;
		}
		int maxlen = findLongestSegment(segments, n);
		displayAll(segments);
		cout << "the maxlen is " << maxlen << endl;
		cout << endl << "please input the numbers of segments:" ;
	}
	system("pause");
}
int commonSegment(const segment &seg_a, const segment &seg_b)
{
	segment commonseg;
	if (seg_a.end<seg_b.start || seg_a.start>seg_b.end)
	{
		commonseg.start = 0;
		commonseg.end = 0;
	}
	else {
		commonseg.start = max(seg_a.start, seg_b.start);
		commonseg.end = min(seg_a.end, seg_b.end);
	}
	return commonseg.end - commonseg.start;
}
int findLongestSegment(const vector<segment>&segments, int size)
{
	vector<int>lens(size );
	lens[0] = 0;
	lens[1] = commonSegment(segments[0], segments[1]);
	int tmplen;
	for (int i = 2; i <size; i++)
	{
		lens[i] = lens[i - 1];
		for (int j = 0; j < i - 1; j++)
		{
			tmplen = commonSegment(segments[i], segments[j]);
			lens[i] = max(lens[i], tmplen);
		}
	}
	for (int i = 0; i < size; i++)
	{
		cout << lens[i] << "  ";
	}
	cout << endl;
	return lens[size - 1];
}

递归方法:

#include <iostream>

#include <algorithm>

#include <vector>



using namespace std;





typedef struct{

    int start;

    int end;

}segment;



bool isShorter(const segment &s1,const segment &s2);

segment commonSegment(const segment &seg_a,const segment &seg_b);

int findLongestSegment(const vector<segment> &segments,int size,segment &maxSegment);



int main()

{

    int n;

    int start,end;

    while(cin>>n){

        vector<segment> segments(n);

        for(int i=0;i<n;i++){

            if(cin>>start && cin>>end){

                segments[i].start=start;

                segments[i].end=end;

            }

        }



        // sort by segment.end

        //sort(segments.begin(),segments.end(),isShorter);



        segment maxSeg;

        int maxLen;



        maxLen=findLongestSegment(segments,n,maxSeg);



        cout<<"Longest Length:"<<maxLen<<endl;

        cout<<"start:"<<maxSeg.start<<endl;

        cout<<"end:"<<maxSeg.end<<endl;

    }



    return 0;

}



bool isShorter(const segment &s1,const segment &s2){

    return s1.end<s2.end;

}





//assume seg_a.end<seg_b.end

segment commonSegment(const segment &seg_a,const segment &seg_b){

    segment commonSeg;

    if(seg_a.end<seg_b.start || seg_a.start>seg_b.end){

        commonSeg.start=0;

        commonSeg.end=0;

    }

    else{

        commonSeg.start=max(seg_a.start,seg_b.start);

        commonSeg.end=min(seg_a.end,seg_b.end);

    }

    return commonSeg;

}



int findLongestSegment(const vector<segment> &segments,int size,segment &maxSegment){

    if(size<=1)

        return 0;



    if(size==2){

        maxSegment=commonSegment(segments[0],segments[1]);

        return maxSegment.end-maxSegment.start;

    }



    // size>2

    // recursive method

    int maxLen,tmpLen;

    segment tmpMaxSeg;

    maxLen=findLongestSegment(segments,size-1,tmpMaxSeg);

    maxSegment=tmpMaxSeg;



    // maxSegment=(maxSegment,commonSeg)

    segment commonSeg;

    for(int i=0;i<size-1;i++){

        commonSeg=commonSegment(segments[i],segments[size-1]);

        tmpLen=commonSeg.end-commonSeg.start;

        if(tmpLen>maxLen){

            maxLen=tmpLen;

            maxSegment=commonSeg;

        }

    }



    return maxSegment.end-maxSegment.start;

}

转载:https://www.cnblogs.com/AndyJee/p/4537376.html

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值