poj1328 Radar Installation
http://poj.org/problem?id=1328
題目大意:假設海岸是一條無限的直線。陸地在海岸線的一邊,大海在另一邊。每個小島都位於海邊。任何雷達裝置,定位在海岸上,只能覆蓋d距離,所以在海中的一個島嶼可以被半徑安裝覆蓋,如果它們之間的距離是最大的d。我們用笛卡爾坐標系統,定義滑行是x軸。海面在x軸上方,陸地在下面。考慮到每個島嶼在海上的位置,並且考慮到雷達裝置的覆蓋範圍,你的任務是編寫一個程序來找出覆蓋所有島嶼的雷達裝置的最小數量。請註意,島嶼的位置用它的x-y坐標表示。輸入由幾個測試用例組成。每個案例的第一行包含兩個整數n (1<=n<=1000)和d,其中n是海中島嶼的數量,d是雷達裝置的覆蓋距離。後面是n行,每個包含兩個代表每個島位置坐標的整數。然後是一個空行來分隔這些案例。輸入由包含一對0的行終止。對於每個測試用例,輸出一行包括測試用例編號,然後是所需的最小數量的雷達安裝。“-1”安裝意味著沒有解決方案。
也就是說在一個笛卡爾坐標系上n個島嶼的坐標 (x,y)給出,要求用最少的雷達能夠覆蓋n個島嶼。當然,如果某一個島嶼的縱坐標如果大於雷達掃描半徑d顯然,此時輸出-1。為了方便表示,我們可以將二維的(x,y)坐標表示,轉化為一維的x坐標區間表示,即利用勾股定理得到每個島嶼所對應的能放置雷達的區間[ xLeft , xRight ]。
算法思想:貪心算法,貪心策略是使每一個雷達盡可能的覆蓋更多的島嶼。即使雷達能覆蓋更多的區間。首先,我們要對得到的區間依照xLeft從小到大進行排序,便於我們進行選擇,先從最小的xLeft對應的島嶼開始,我們設置一個在x軸從左到右遍歷的temp並初始化為排序後第一個島嶼的xRight(為了覆蓋更多的區間)。那麽接下來的一個島嶼,有三種情況:
第一種情況顯然需要多加一個雷達,並置temp為下一個雷達的xRight;
第二種情況不需要加雷達,temp的值保持不變;
第三種情況不需要加雷達,但是temp的值要置為下一個雷達的xRight(這樣才能覆蓋此雷達);
PS:如果不了解STL <algorithm>頭文件sort()函數,可以查一下,也可以自己寫一個排序算法,對區間排序。
1 #include <iostream> 2 #include <algorithm> 3 #include <cmath> 4 using namespace std; 5 struct coordinate//存儲x軸區間的結構 6 { 7 double xLeft; 8 double xRight; 9 }; 10 bool compare(coordinate a_coordinate,coordinate b_coordinate)//sort第三個參數 11 { 12 return a_coordinate.xLeft <= b_coordinate.xLeft; 13 } 14 int main(void) 15 { 16 int n;//n個島 17 double d;//雷達掃射半徑 18 int testCase = 0;//測試案例數 19 while (cin >> n >> d && (n != 0 && d != 0)) 20 { 21 coordinate *coor = new coordinate[n + 1]; 22 bool sovable = true;//默認可解 23 if (d < 0) sovable = false; 24 testCase++;//測試案例數+1 25 double x, y; 26 for (int i = 1; i <=n; ++i) 27 { 28 cin >> x >> y; 29 if (y > d)//如果島的y軸坐標超出雷達掃射半徑,問題不可解 30 sovable = false; 31 double temp = sqrt(d*d - y * y);//勾股定理求雷達覆蓋能達到距離 32 coor[i].xLeft = x - temp; 33 coor[i].xRight = x + temp; 34 } 35 sort(coor + 1, coor + n +1 , compare);//按左值從xiao到da排序 36 int leida = 1;//至少一個雷達 37 double temp=coor[1].xRight;//從最左邊的那一段的右端開始遍歷 38 for (int i = 2; i <=n; ++i) 39 { 40 if (temp<coor[i].xLeft)//如果第二段的左值小於第一段右值 41 { 42 temp = coor[i].xRight; 43 leida++;//顯然需要增加雷達 44 } 45 else//如果第二段的左值大於等於第一段右值 46 { 47 if (temp>coor[i].xRight)//如果第二段的右值小於第一段右值 48 { 49 temp = coor[i].xRight;//更新遍歷的值 50 } 51 else 52 { 53 54 } 55 } 56 } 57 leida = sovable ? leida : -1;//如果問題不可解賦值-1 58 cout << "Case " << testCase << ": " << leida << endl;//End 59 delete[] coor; 60 coor = NULL; 61 } 62 return 0; 63 }
poj1328 Radar Installation