「巧克力」題解
阿新 • • 發佈:2021-07-13
因為不開 long long 難了我好久的「巧克力」……我太蒻了。
的位置列舉就可以),再在剩下的區域中儘量平均分——容易證明這樣是最優的。
「巧克力」題解
題目
學校的網站,一般人上不去。題目連結:Link。
有一塊高 \(H\) 塊,寬 \(W\) 塊的巧克力, 小明將其分為 \(3\) 塊。他只能沿著每塊巧克力的邊緣切割,並且切割的形狀必須是一個長方形。 小明希望儘可能的平均切割,也就是他希望 \(S_{max} – S_{min}\) 儘可能的小, \(S_{max}\) 是最大那一份的面積 (包含的塊數), \(S_{min}\) 是最小那一份的面積。 求 \(S_{max} – S_{min}\) 的最小值。
程式碼
如果光看樣例,會簡單地以為答案是 \((H \bmod 3) \times (W \bmod 3)\),其實不然。這道題本質上就是一個列舉優化的程式碼。列舉一刀切的位置(這裡可以再優化,只在 \(\frac{1}{3}H \pm 5\)
當然了,最開始列舉的那刀可以橫切頁可以豎切,所以這樣完之後 swap(H,W)
一下就可以了。
資料範圍到了 \(10^5\)——十年 OI 一場空,不開 long long 見祖宗!程式碼如下:
#include <bits stdc++.h=""> using namespace std; #define ll long long ll x, y, ans; void mov(ll a, ll b) {ans = min(ans, max(max(a, b), x * y - a - b) - min(min(a, b), x * y - a - b));} // 算三塊中的最大值減去最小值,更新 ans void movs() { for (ll i = 1; i < x; i++) { ll z = x - i; mov(i * y, y / 2 * z); mov(i * y, z / 2 * y); } } // 儘量平均分 int main() { cin >> x >> y; // 輸入 ans = x * y; // ans 初始值 xy movs(); swap(x, y); movs(); // 簡單操作,記得 swap cout << ans << endl; // 輸出嘍 return 0; }
\(10\) 個點跑了 \(21\) ms,稍微有點多,不過程式碼實在很短了。壓行程式碼:
#include<bits/stdc++.h> using namespace std; #define ll long long ll x,y,ans; void mov(ll a,ll b){ans=min(ans,max(max(a,b),x*y-a-b)-min(min(a,b),x*y-a-b));} void movs(){for(ll i=1;i<x;i++) {ll z=x-i;mov(i*y,y/2*z);mov(i*y,z/2*y);}} int main(){cin>>x>>y;ans=x*y;movs();swap(x,y);movs();cout<<ans;return 0;}