「巧克力」题解

时间:2021-07-13
本文章向大家介绍「巧克力」题解,主要包括「巧克力」题解使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

「巧克力」题解

题目

学校的网站,一般人上不去。题目链接: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;}

原文地址:https://www.cnblogs.com/liuzimingc/p/chocolate.html