C基於貪心思想實現網格盒子歐幾里得距離不等於固定數的最大分佈
阿新 • • 發佈:2021-01-20
題目:二貨小易有一個W*H的網格盒子,網格的行編號為0 ~ H-1,網格的列編號為0 ~ W-1。每個格子至多可以放一塊蛋糕,任意兩塊蛋糕的歐幾里得距離不能等於2。對於兩個格子座標(x1,y1),(x2,y2)的歐幾里得距離為: (x1-x2) * (x1-x2) + (y1-y2) * (y1-y2) ) 的算術平方根。小易想知道最多可以放多少塊蛋糕在網格盒子裡。
引用:引用原文連結
滿足歐幾里得距離不等於2,則同一行中任意兩塊蛋糕的距離一定大於等於2或者為0才可以,在任意斜對角線上的蛋糕都不可能滿足歐幾里得距離為2,貪心思想盡可能實現兩個蛋糕一起放
-
先考慮最簡單的情況:行數、列數都是 4 的倍數
如圖,這是一個 4 × 8 大小的盒子:圖中一個黃色圓佔了四個空格,這四個空格可以放四塊蛋糕並且滿足歐幾里得距離小於2,放完4塊蛋糕蛋再隔兩個空再放入, 我把四個格子看成一組
從左上角開始四個一組放蛋糕,每放一組空一組:
由於行列數都是 4 的倍數,而一組蛋糕只要佔用兩行兩列,所以放入的黃點數量必定為偶數個,且放入蛋糕數量和空出的格子數量相等。
若設總格子數為:S = W * H,則放入蛋糕數為 S / 2。
並且,由下面四幅圖我們可以推出:只要行數或列數為4的倍數,上式仍然成立(下圖中半圓表示兩塊蛋糕,)
-
如果行數和列數都不是4的整數倍,但是行數列數都為 2 的倍數,我們依然可以將每個盒子用四個一組的蛋糕放滿,但是情況和 1 不一樣了,於是出現了這種情況:
可以發現:黃圈總是比空圈多一個,若設總的組數為 S = W×H÷4,記蛋糕組數為 count,則使用int型別的除法可得,count = (S + 1)/2。蛋糕數即為4倍的count。 -
若只有行數或列數一方為 2 的倍數,另一個為奇數,則會出現某一行或列的黃圈被切了一半的情況,只需要補一個對稱的盒子再使用情況2中的方法進行處理即可。 若是行列數都是奇數,同樣可以補成2的形式,例如:
如果行和列只有一方是奇數則總的組數為S = W×H×2÷4,count = (S + 1)/2,蛋糕數即為count÷2×4,如果行和列都是奇數則總的組數為S = (W×2)×(H×2)÷4,count = (S + 1)/2,蛋糕數即為count÷4×4
由於在計算組數時候容易出現小數,因此在程式碼中儘量求避免單獨的蛋糕組數
#include<stdio.h>
int main(){
int L, H, S, count; //L列,H是行,count組數也用來表示是蛋糕得數量
scanf(("%d %d"),&L,&H );
//行或者列有一方是4的整數倍
if(L% 4 == 0 || H % 4 == 0){
S = L * H;
count = S/2;
//情況2:行和列都是2的整數倍
else if(L % 2 == 0 && H % 2 == 0){
S = L * H / 4;
count = (S + 1) / 2;
count *= 4;
}
//行和列有一方是2的整數倍,另一方奇數
else if(L % 2 == 0 || H % 2 == 0){
//S先乘2把它變成行列都是偶數的情況,再求組數除以4, 轉成情況2
S = (L * H *2)/4;
count = (S + 1);
}
//行和列都是奇數
else{
//擴充4倍, 轉成情況2
S = (L * 2) * (H * 2) / 4;
count = (S + 1) / 2; //直接計算避免小數出現
}
printf("%d\n",count);
return 0;
}