標籤:
題目:X軸上有N條線段,每條線段包括1個起點和終點。線段的重疊是這樣來算的,[10 20]和[12 25]的重疊部分為[12 20]。給出N條線段的起點和終點,從中選出2條線段,這兩條線段的重疊部分是最長的。輸出這個最長的距離。如果沒有重疊,輸出0。 思路:1、暴力計算依次計算兩兩線段之間的重疊長度,但複雜度太高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])))
代碼:
#include <iostream>#include <algorithm>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.endsegment commonSegment(const segment &seg_a,const segment &seg_b){ segment commonSeg; if(seg_a.end<seg_b.start){ commonSeg.start=0; commonSeg.end=0; } else{ commonSeg.start=seg_b.start; commonSeg.end=seg_a.end; } return commonSeg;}int findLongestSegment(const vector<segment> &segments,int size,segment &maxSegment){ if(size<=0) return 0; /* if(size==1){ maxSegment.start=segments[0].start; maxSegment.end=segments[0].end; return maxSegment.end-maxSegment.start; } */ if(size==2){ maxSegment=commonSegment(segments[0],segments[1]); return maxSegment.end-maxSegment.start; } // size>2 // dynamic programming 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;}運行結果:
(演算法)最長重疊線段或區間