每天一道ACM 8 8 給草坪裝灑水裝置

2021-08-22 11:57:30 字數 2974 閱讀 6801

題目**於網上,南陽理工大學的acm練習

現有一塊草坪,長為20公尺,寬為2公尺,要在橫中心線上放置半徑為ri的噴水裝置,每個噴水裝置的效果都會讓以它為中心的半徑為實數ri(0

第一行m表示有m組測試資料

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

輸出所用裝置的個數

拿到題目先審題,題目裡有兩個東西,噴水裝置和草坪,每個噴水裝置可以澆灌一定圓面積的草坪,草坪是乙個20*2的長方形,要求用最少的噴水裝置澆灌草坪,輸出最小的這個數量。

容易想到如果能寫出乙個判斷二維幾何圖形是否重合函式的話,就應該能解決這個問題但思考一下就能發現這個函式很難寫的,那如果寫一維線段是否重合呢?我們發現這個函式就很好寫了。所以我們接下來就先把題目抽象化簡成乙個比較一維區間的問題。

容易發現題目的影象是上下對稱的,所以我們只要保證上方被覆蓋就可以滿足要求,因為要轉化為一維區間的比較,我們用一些橫線去截影象,橫線從中軸線往上掃,可以看出當橫線與上方邊界重合時邊界的區間有最小值,於是我猜測原題等價於在中軸線上的圓與上邊界的重合部分可以覆蓋整個上邊界。那麼我們就來試著證明一下。

如果上邊界被全覆蓋,那麼整個草坪肯定被覆蓋,所以得必要性。

如果整個草坪被覆蓋,那麼上邊界肯定被覆蓋,所以得充分性。

由上述分析我們已經將題目轉化為比較噴水圓與上邊界的交線是否覆蓋整條上邊界。那麼這些圓怎麼放呢?易得我們安放這些圓於中使得其與上邊界的左交點為上邊界左頂點或已放置圓的右交點,而安放的順序應該是按照先放大的再放小的,以保證所需的最少。按照這個思路,我們只要算出所有噴水裝置與上邊界的交線長度(與位置無關)並從大到小排序累加,當和大於20時,已加的噴水裝置個數即為最小數量。以上就將原題化簡為了乙個易與編寫的等價命題。

以下為按照上述思路編寫的**,先構造了乙個噴水裝置的類便於呼叫其相關資料。

class watering

watering(double r)

void set_watering(double r)

double get_range()

double get_ri()

};

很簡單的類,就不多說了

接下來是功能函式的編寫

int functin(double *waterer,int lenth)

;//int lenth = 10;

watering *waterings = (watering*)new watering[lenth];

for (int i = lenth; i > 0; i--)}}

for (int i = 0; i < lenth; i++)

waterings[i].set_watering(waterer[i]);

//for (int i = 0; i < lenth; i++)

// cout << waterings[i].get_range() <<",";

double

count = 0;

for (int i = 0; i < lenth; i++)

else}}

//while (1);

cout << "can't water whole lawn"

<< endl;

return

0;}

這裡有個小問題,函式內new的記憶體需不需要手動用delete釋放?望看見的大神告知一下。

然後是實現題中的輸入輸出方式,

int main()

for (int i = 0; i < 2; i++)

//while (1);

}

兩個小問題,乙個是cin讀資料什麼時候用換行,什麼時候用空格,我在編寫中有過疑問,但沒有深究,有空研究一下。

還有乙個問題,怎麼讓vs跑程式程式結束時不自動關閉視窗?不用while(1).

#include 

#include

#define pi 3.14159

#include 

#include

#define pi 3.14159

using

namespace

std;

class watering

watering(double r)

void set_watering(double r)

double get_range()

double get_ri()

};int functin(double *waterer,int lenth)

;//int lenth = 10;

watering *waterings = (watering*)new watering[lenth];

for (int i = lenth; i > 0; i--)}}

for (int i = 0; i < lenth; i++)

waterings[i].set_watering(waterer[i]);

//for (int i = 0; i < lenth; i++)

// cout << waterings[i].get_range() <<",";

double count = 0;

for (int i = 0; i < lenth; i++)

else}}

//while (1);

cout

<< "can't water whole lawn"

<< endl;

return0;}

int main()

for (int i = 0; i < 2; i++)

//while (1);

}

因為沒有賬號,所以也沒有提交檢視對錯,只是試了測試資料,所以如果有錯誤歡迎提出。

有什麼覺得可以改進或者簡化的地方也請不客氣的指教

over

每天一道Linux命令

no.1 以下的命令得在 自動執行 06 03 3 lp usr local message mail s server message root a.每週三06 03分 b.每週六03 03分 c.每週三03 06分 d.每週六03 06分 no.2 下列關於管道 pipe 通訊的敘述中,正確的是...

每天一道演算法題

no.1 棧是特殊的線性表,它。a.對 b.錯答案 錯,它的插入和刪除都是在同一端進行的。no.2 n個葉子節點的滿二叉樹 除了葉子節點,每個節點都有兩個孩子 總共有多少個節點?a.2n 1 b.2n c.n 1 d.n答案 a 滿二叉樹我們講過了,度為0的節點比度為2的加點多乙個。滿二叉樹是特殊的...

每天一道Linux題

1 為了檢視不斷更新的日誌檔案,可以使用的指令是 a.cat n b.vi c.more d.tail f 答案 這道題沒什麼好說的,使用tail f可以看到實時更新的日誌檔案,選d.2 檔案exer1的訪問許可權為rw r r 現要增加所有使用者的執行許可權和同組使用者的寫許可權,下列哪個命令是對...