1. 程式人生 > 實用技巧 >小H的小屋

小H的小屋

題解 [NOI2004]小H的小屋

前記

又鴿了好久,這回可要努力更新了

2019.6.2,痛下殺心,把電腦上所有的遊戲都刪掉了,提前160天奮力備考NOIP。目標:A類省隊!

我是傳送門

題解

這道題唯一的難點就在於貪心

從簡單開始,假如一個矩形需要分成兩部分,要求面積最小(參照題意)。那麼均分肯定時最優解

如圖,紫色是大的矩形,橙色是均分的兩個小矩形,藍色是非均分的兩個小矩形。顯而易見的是,橙色面積要比藍色小。由於是貪心嘛其實是懶得嚴格證明,我們發現分成兩個的情況下,均分最優

那麼把情況擴充套件以下,由於貪心思想這回是因為我不會嚴格證明,均分思想可以推廣到分成更多的小矩形的情況中

好了有了均分的思想,還有一個問題:假如\(n \mod m \ne 0\)

怎麼辦?

也好辦,儘可能湊成對齊的就好了嘛

\ 北牆 南牆
一部分 \(ln = m-n\mod m\) \(lr = \lfloor \frac{n}{m} \rfloor\)
另一部分 \(rn = n\mod m\) \(rs = \lfloor \frac{n}{m} \rfloor + 1\)

醬紫就可以保證滿足均分思想

假設\(area(x,y,k)\)表示在橫座標長度為y的矩形中分x份,斜率為k

double area(int x,int y,double k){   // x kuai in y len
    return (double)(x-y%x)*(y/x)*k*(y/x)+(y%x)*(y/x+1)*k*(y/x+1);
}

\(n\mod m=0\)

\(ans=area(n,100,k1)+area(m,100,k2)\)

\(n\mod m\ne 0\)

\(ans=min_{i=ln\times lr} ^ {100-rn*rs} area(ln,i,k1)+area(ln\times ls,i,k2)+area(rn,100-i,k1)+area(rn\times rs,100-i,k2)\)

然後據說ans關於i是個單峰函式,不過反正i最大不過迴圈100次,我也不會證明這個函式的單調性,就算了吧。

code:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

int m,n,ln,ls,rn,rs;
double k1,k2,ans;

double area(int,int,double);

int main(){
    #ifndef ONLINE_JUDGE
    freopen("test.in","r",stdin);
    #endif

    scanf("%lf%lf%d%d",&k1,&k2,&m,&n);

    if(n%m==0){
        ans+=area(m,100,k1);
        ans+=area(n,100,k2);
        printf("%.1lf\n",ans);
        return 0;
    }

    ln=m-n%m; ls=n/m;
    rn=n%m; rs=(n/m+1);

    ans=2147483647.0;
    for(int i=ln*ls;i<=100-rn*rs;++i){

        double tmp=0.0;
        tmp+=area(ln,i,k1);
        tmp+=area(ln*ls,i,k2);
        tmp+=area(rn,100-i,k1);
        tmp+=area(rn*rs,100-i,k2);
        ans=min(ans,tmp);
    }
    printf("%.1lf\n",ans);

    return 0;
}

double area(int x,int y,double k){   // x kuai in y len
    return (double)(x-y%x)*(y/x)*k*(y/x)+(y%x)*(y/x+1)*k*(y/x+1);
}

後記

距 NOIp2019 還剩 159 天

你已經在洛谷連續打卡了 266 天,獎勵積分 4

衝鴨!