1. 程式人生 > 其它 >C基於貪心思想實現網格盒子歐幾里得距離不等於固定數的最大分佈

C基於貪心思想實現網格盒子歐幾里得距離不等於固定數的最大分佈

技術標籤:演算法小記演算法

題目:二貨小易有一個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,貪心思想盡可能實現兩個蛋糕一起放

  1. 先考慮最簡單的情況:行數、列數都是 4 的倍數

    在這裡插入圖片描述
    如圖,這是一個 4 × 8 大小的盒子:圖中一個黃色圓佔了四個空格,這四個空格可以放四塊蛋糕並且滿足歐幾里得距離小於2,放完4塊蛋糕蛋再隔兩個空再放入, 我把四個格子看成一組
    從左上角開始四個一組放蛋糕,每放一組空一組:

    由於行列數都是 4 的倍數,而一組蛋糕只要佔用兩行兩列,所以放入的黃點數量必定為偶數個,且放入蛋糕數量和空出的格子數量相等。
    若設總格子數為:S = W * H,則放入蛋糕數為 S / 2。
    並且,由下面四幅圖我們可以推出:只要行數或列數為4的倍數,上式仍然成立(下圖中半圓表示兩塊蛋糕,)
    在這裡插入圖片描述

  2. 如果行數和列數都不是4的整數倍,但是行數列數都為 2 的倍數,我們依然可以將每個盒子用四個一組的蛋糕放滿,但是情況和 1 不一樣了,於是出現了這種情況:

    . 在這裡插入圖片描述
    可以發現:黃圈總是比空圈多一個,若設總的組數為 S = W×H÷4,記蛋糕組數為 count,則使用int型別的除法可得,count = (S + 1)/2。蛋糕數即為4倍的count。

  3. 若只有行數或列數一方為 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;
}