1. 程式人生 > >南陽理工ACM:噴水裝置(一)題目及解法

南陽理工ACM:噴水裝置(一)題目及解法

描述

現有一塊草坪,長為20米,寬為2米,要在橫中心線上放置半徑為Ri的噴水裝置,每個噴水裝置的效果都會讓以它為中心的半徑為實數Ri(0<Ri<15)的圓被溼潤,這有充足的噴水裝置i(1<i<600)個,並且一定能把草坪全部溼潤,你要做的是:選擇儘量少的噴水裝置,把整個草坪的全部溼潤。

輸入

第一行m表示有m組測試資料 每一組測試資料的第一行有一個整數數n,n表示共有n個噴水裝置,隨後的一行,有n個實數ri,ri表示該噴水裝置能覆蓋的圓的半徑。

輸出

輸出所用裝置的個數

樣例輸入

2
5
2 3.2 4 4.5 6 
10
1 2 3 1 2 1.2 3 1.1 1 2

樣例輸出

2
5

首先從網上抄的一張圖如下

1.每個裝置的覆蓋距離是是2*sqrt(r*r-1),就是我標註的紅色長度的二倍。這個就滿足了不會出現覆蓋不了的區域。

2.然後進行排序,從大到小進行排序。貪心演算法,既然要求最少的裝置那就儘量用大的然後在考慮小的裝置。

一般的排序方法就可以了。程式碼如下:

#include<stdio.h> #include<math.h>   //勾股定理函式   float Tri(float c, float a) {     return sqrt(c*c - a*a); }   int main() {     int m,n;     float a[601], sum,t;     scanf("%d", &m);     while (m--)     {         sum = 0.0;         scanf("%d", &n);         for (int i = 0; i < n; i++)         {             scanf("%f", &a[i]);//依此讀入陣列,準備排序         }           //排序演算法(冒泡)         for (int i = 0; i < n - 1; i++)         {             for (int j = i + 1; j < n; j++)             {                 if (a[i] < a[j])                 {                     t = a[i];                      a[i] = a[j];                     a[j] = t;                 }             }         }           //從高到低開始選擇         for (int i = 0; i < n; i++)         {             sum += (2*Tri(a[i],1.0));             if (sum >= 20)             {                 printf("%d\n", i + 1);                 break;             }         }       }     getchar();     getchar();     return 0; }