<pre class="cpp" name="code">
一 。貪心策略:將雷達放置在合適的地方,使得包含的島嶼數量最多。
二。貪心策略具體分析
我們採用從左到右放置雷達。假設左邊第一個島嶼是A(Xa,Ya),從左到右的島嶼依次是A B C ....
我們可以計算出島嶼A的雷達區間 : [Xa_left,Xa_right] , 使得在這個區間的雷達都可以覆蓋到島嶼A。
Xa_left = Xa - sqrt (d^2 - Ya^2) ; Xa_right = Xa + sqrt(d^2 - Ya^2);
(其中d是雷達的輻射範圍)
此時,可以將情況分爲三種:如下圖所示
三。快速排序
1.在這裏定義了數據類型island,是指在這個區間[ x_left , x_right ]放置的雷達,都可以輻射到島嶼A 。同時,定義了一千個島嶼的數組arr[1000],裏面分別存放了每個島嶼的雷達區間。
typedef struct island{ //定義一個島嶼所需雷達的區間
double x_left;
double x_right;
}island;
island arr[1000];
2.因爲我們是從左往右放置雷達,所以排序的時候,是按x_left從小到大排序。
在這裏,需要注意的是,交換數組裏的x_left的同時,也要交換x_right。否則數組裏存放的x_left和x_right將不對應。
int partition1(island* a ,int low, int high){ //快速排序,以x_left從小到大排序
double temp = a[low].x_left;
double temp_left;
double temp_right;
while(low<high){
while(low<high && temp <= (a[high].x_left)){
high--;
}
temp_left = a[high].x_left; //交換的是arr[high]和arr[low]
a[high].x_left = a[low].x_left;
a[low].x_left = temp_left;
temp_right = a[high].x_right;
a[high].x_right = a[low].x_right;
a[low].x_right = temp_right;
while(low<high && temp >= (a[low].x_left)){
low ++;
}
temp_left = a[high].x_left; //交換的是arr[high]和arr[low]
a[high].x_left = a[low].x_left;
a[low].x_left = temp_left;
temp_right = a[high].x_right;
a[high].x_right = a[low].x_right;
a[low].x_right = temp_right;
}
return low;
}
void fastsort(island* a ,int low, int high){ //快速排序,以x_left從小到大排序
int pivot;
if(low<high){
pivot = partition1(a,low,high);
fastsort(a,low,pivot-1);
fastsort(a,pivot+1,high);
}
}
四。貪心策略的實現
用cur表示,當前雷達可放置的最右端。
void Greedy(island* a , int n){
double cur =a[0].x_right; //當前最右端的雷達
int i =0;
for(i=1;i<n;i++){
if(cur < a[i].x_left){ //需要一個新的雷達
number++;
cur = a[i].x_right;
}else if(cur > a[i].x_right){// 此時島嶼0的雷達座標包含島嶼1的雷達座標, 所以當前雷達座標選用雷達1的
cur = a[i].x_right;
}
}
}
五。查看完整代碼:
其中需要注意的是,輸入的輻射範圍d<=0時和y軸座標>d時的處理,即無法完成雷達探測。輸出-1.
#include <stdio.h>
#include <stdlib.h>
#include<math.h>
#define MAX 65535
typedef struct island{ //定義一個島嶼所需雷達的區間
double x_left;
double x_right;
}island;
island arr[1000];
int number=1; //需要的雷達數量
int partition1(island* a ,int low, int high){ //快速排序,以x_left從小到大排序
double temp = a[low].x_left;
double temp_left;
double temp_right;
while(low<high){
while(low<high && temp <= (a[high].x_left)){
high--;
}
temp_left = a[high].x_left; //交換的是arr[high]和arr[low]
a[high].x_left = a[low].x_left;
a[low].x_left = temp_left;
temp_right = a[high].x_right;
a[high].x_right = a[low].x_right;
a[low].x_right = temp_right;
while(low<high && temp >= (a[low].x_left)){
low ++;
}
temp_left = a[high].x_left; //交換的是arr[high]和arr[low]
a[high].x_left = a[low].x_left;
a[low].x_left = temp_left;
temp_right = a[high].x_right;
a[high].x_right = a[low].x_right;
a[low].x_right = temp_right;
}
return low;
}
void fastsort(island* a ,int low, int high){ //快速排序,以x_left從小到大排序
int pivot;
if(low<high){
pivot = partition1(a,low,high);
fastsort(a,low,pivot-1);
fastsort(a,pivot+1,high);
}
}
void Greedy(island* a , int n){
double cur =a[0].x_right; //當前可探測的最右端
int i =0;
for(i=1;i<n;i++){
if(cur < a[i].x_left){ //需要一個新的雷達
number++;
cur = a[i].x_right;
}else if(cur > a[i].x_right){// 此時島嶼0的雷達座標包含島嶼1的雷達座標, 所以當前雷達座標選用雷達1的
cur = a[i].x_right;
}
}
}
int main()
{
int n=0;
int d=0;
int caseNum = 0;
//freopen("input.txt","r",stdin);
while(scanf("%d%d",&n,&d)){
if(n==0 && d==0){
break;
}
memset(arr,MAX,sizeof(arr)); //數組初始化爲最大值
number = 1;
caseNum++;
int i=0;
int flag = 0;
int x ,y;
for(i=0;i<n;i++){
scanf("%d%d",&x,&y); //讀取每一個島嶼的座標
if(flag ==1 || y>d || d<=0){ //y>d和d<=0, 說明雷達無法覆蓋到島嶼,標誌位置1
flag = 1; //
continue; //continue語句,需要繼續讀接下來的數據
}
double temp = sqrt((double)(d*d-y*y));
arr[i].x_left = x -temp;
arr[i].x_right = x + temp;
}
if(flag == 1){
printf("Case %d: -1\n",caseNum); //如果不能查找,那麼則不進行排序和貪心
}else{
fastsort(arr,0,n-1);
Greedy(arr,n);
printf("Case %d: %d\n",caseNum,number); //天坑!!!!"case 1:"後面還有個空格
}
}
return 0;
}