貪心演算法-----區間覆蓋問題
阿新 • • 發佈:2019-01-27
(一)點覆蓋區間(雷達/灌溉噴頭)
題目描述:假設海岸線是一條無限延伸的直線。陸地在海岸線的一側,而海洋在另一側。每一個小的島嶼是海洋上的一個點。雷達坐落於海岸線上,只能覆蓋d距離,所以如果小島能夠被覆蓋到的話,它們之間的距離最多為d。題目要求計算出能夠覆蓋給出的所有島嶼的最少雷達數目。對於每個小島,我們可以計算出一個雷達所在位置的區間。
演算法實現: //2018年6月11日與遼寧瀋陽東北大學 #include <iostream> #include <cmath> #include <algorithm> using namespace std; struct Qujian { double start, end; }; int radarNum = 1; //這個函式寫法值得學習 /************************************************************/ int cmp(const void *a, const void *b) { return (*(Qujian *)a).start>(*(Qujian *)b).start ? 1 : -1; } /**********************************************************/ int main(void) { double x, y; cout << "請輸入島嶼數目和雷達最大探測距離 "; int num_island; double DisMax; cin >> num_island >> DisMax; Qujian qujian[50]; for (int i = 0; i < num_island; ++i) { cout << "請輸入第"<<i+1<<"個島嶼的橫縱座標: "<<endl; cin >> x >> y; if (y > DisMax) { cout << " 這個島嶼檢測不到" << endl; exit(-1); } qujian[i].start = x - sqrt(DisMax*DisMax -y*y); qujian[i].end = x +sqrt(DisMax*DisMax - y*y); } qsort(qujian, num_island, sizeof(qujian[0]), cmp); for (int j = 1; j <= num_island; ++j) { if (qujian[j].start >= qujian[0].start&&qujian[j].end <= qujian[0].end) { qujian[0].end = qujian[j].end; } if (qujian[j].start > qujian[0].end) { //qujian[0].start = qujian[j].start; qujian[0].end = qujian[j].end; radarNum++; } } cout << "需要雷達總數是:" << radarNum << endl; return 0; }
問題轉化為如何用盡可能少的點覆蓋這些區間。先將所有區間按照左端點大小排序,初始時需要一個點。如果兩個區間相交而不重合,我們什麼都不需要做;如果一個區間完全包含於另外一個區間,我們需要更新區間的右端點;如果兩個區間不相交,我們需要增加點並更新右端點。
草圖:
(二)線段覆蓋區間
//2018年6月11日於遼寧瀋陽 //Author:Mr Yang //(二)線段覆蓋區間 // //題目描述: // //用i來表示x座標軸上座標為[i - 1,i]的長度為1的區間,並給出n(1≤M≤200)個不同的整數,表示n個這樣的區間。 //現在要求畫m條線段覆蓋住所有的區間, //條件是:每條線段可以任意長,但是要求所畫線段的長度之和最小,並且線段的數目不超過N(1≤N≤50)。 //輸入: //輸入包括多組資料,每組資料的第一行表示點數n和所需線段數m,後面的n行表示點的座標 //輸出: //輸出每組按規定線段條數被覆蓋的線段的最短總長度。 //示例輸入: //5 3 //1 3 5 8 11 //示例輸出: //7 //演算法思想: //第一步將所有區間間距排序,再連線間距最短的兩個線段(間距大小並列的只連線一個),統計這時候有多少條線段,如果大於限制線段樹就繼續連線區間間距次小的兩個區間......直到線段數目等於規定最大線段數為止 //演算法實現: #include <iostream> #include <algorithm> #include <cmath> #define N 200 using namespace std; struct Qujian { int start, end; }; Qujian qujian[200]; //存放輸入區間 //int cmp(const int&a, const int&b) //{ //return (*(Qujian *)a).start>(*(Qujian *)b).start ? 1 : -1; // return a //} int main() { int PointNum, segmentLimit; cout << "請輸入區間數目和線段限制最大數:" << endl; cin >> PointNum >> segmentLimit; cout << "請輸入具體區間: " << endl; int buf_Point; for (int j = 0; j <PointNum; ++j) { cin >> buf_Point; qujian[j].start = buf_Point - 1; qujian[j].end = buf_Point; } int Distance[N] = {-1}; //Distance[N]存相鄰區間的距離 for (int j = 0; j < PointNum-1; j++) { Distance[j] = qujian[j + 1].start - qujian[j].end; } //qsort(Distance, PointNum - 1, sizeof(Distance[0]), cmp); sort(Distance, Distance + PointNum - 1); //cout << Distance[0] << Distance[1] << Distance[2] << Distance[3]<< endl;看看排序拍的對不 int ResLength = 0; int SegmentNum = PointNum; for (int j = 0; j < PointNum - 1; ++j) { if (Distance[j] > 0&&j==0) { ResLength = Distance[j] + 2; SegmentNum--; if (SegmentNum == segmentLimit) { ResLength += (PointNum - j - 2);//ResLength=ResLength+(PointNum-1-(j+1) break; } } else if (Distance[j] > 0 && j > 0) { ResLength = ResLength+ Distance[j] + 1; SegmentNum--; if (SegmentNum == segmentLimit) { ResLength+=(PointNum - j - 2); break; } } } cout << ResLength << endl; return 0; }
參考:https://blog.csdn.net/cordova/article/details/50853147
轉載必須註明出處