分巧克力(二分)

题目来源:1227. 分巧克力 - AcWing题库

主要思路

先用一个结构体数组存每一个矩形的长和宽,然后直接二分枚举答案

代码

#include<iostream>
#include<algorithm>
using namespace std;
const int N = 1e5 + 10;
int k, n;
struct chocolate
{
    int h;
    int w;
    int s;//这里的s其实并没有用,这是刚开始做的记录一下错误的原因
}a[N];
bool check(int x)
{
    int sum = 0;//用来记录可以分得得巧克力的总数
    for (int i = 1; i <= n; i++)
    {
        // if(a[i].h>=x&&a[i].w>=x)//这样写是错的,后面会解释
        //     sum += a[i].s / (x * x);
        sum += (a[i].w / x) * (a[i].h / x);
    }
    if (sum < k)//巧克力总数不够,则需要将每块巧克力的大小变小
        return false;
    return true;
}
int main()
{
    cin >> n >> k;
    for (int i = 1; i <= n; i++)
    {
        int x, y;
        cin >> x >> y;
        a[i].h = x;
        a[i].w = y;
        a[i].s = x * y;//不需要
    }
    int l = 0, r = 1e5 + 1;
    while (l + 1 != r)
    {
        int mid = (l + r) >> 1;
        if (check(mid))
            l = mid;
        else
            r = mid;
    }
    cout << l << endl;
    return 0;
}

注意点

1、这里的长和宽也可以分别用两个数组来存,不一定要用结构体来存

2、最最重要的也易错的是check函数里面sum的求法:

刚开始时本人思路是通过计算每块巧克力的面积,想着除以要分得的巧克力的面积就可以得到分了多少个,而且我还特别判断了每块大巧克力的边长够不够切,结果调试了很久

总是遇到一个样例不能过:

50 100
5 4
9 20
8 3
20 7
14 14
17 9
2 11
16 14
8 16
5 13
20 7
19 2
4 8
6 2
2 7
13 10
1 3
8 16
6 20
1 5
11 10
19 7
20 8
11 14
17 8
5 8
3 15
6 19
5 8
3 18
19 16
8 13
20 14
5 7
14 11
20 18
15 18
5 1
13 1
3 5
2 2
15 16
13 11
8 9
8 11
11 3
5 5
16 2
10 20
12 6

这个样例的标准输出是5,而按照我的写法输出是6

然后就一直调试,一步一步看,最后发现我写的代码当小巧克力的边长为6时分到的小巧克力的总数会大于k,但是别人的代码这样分的数量小于k。

最后通过求助大佬,终于明白为什么我这样写有问题

问题分析

来看一个数据:假设原来的巧克力是3×3的正方形,要得到2×2的小巧克力,问可以切几块

如果按注释部分计算即

if(a[i].h>=x&&a[i].w>=x)
             sum += a[i].s / (x * x)

sum=(3*3)/(2*2)=2算出来比正确答案多一,这也就解释了为什么上面样例我的答案比正确答案多一,因为按照这种计算方法多计算了

正确计算方法:

sum += (a[i].w / x) * (a[i].h / x);

sum=(3/2)*(3/2)=1,算出来是正确结果

这种计算方法怎么理解?

a[i].w / x表示可以分多少行,a[i].h / x表示可以分多少列

例如当a[i].w =4,a[i].h=6,x=2

可以分得(a[i].w/ x)*(a[i].h/x)=6个小巧克力

这样就可以避免出现多算少算的问题

在Python中,对商品按功能分类可以使用字典数据结构来实现。具体实现方法如下: 1. 首先创建一个字典,用于存储商品分类信息,例如: ``` goods_dict = { '家电': [], '数码产品': [], '家居用品': [], '食品饮料': [], '服装鞋帽': [], '美容护肤': [] } ``` 2. 接着读取商品数据,将每个商品根据其功能分类加入到对应的分类列表中,例如: ``` # 假设商品数据存储在一个二维列表中,每个元素包括商品名称和功能分类 goods_data = [ ['电视机', '家电'], ['洗衣机', '家电'], ['手机', '数码产品'], ['平板电脑', '数码产品'], ['床上用品', '家居用品'], ['餐具', '家居用品'], ['牛奶', '食品饮料'], ['巧克力', '食品饮料'], ['外套', '服装鞋帽'], ['运动鞋', '服装鞋帽'], ['面霜', '美容护肤'], ['洗面奶', '美容护肤'] ] # 根据功能分类将商品加入到对应的列表中 for goods in goods_data: goods_name = goods[0] goods_category = goods[1] if goods_category in goods_dict: goods_dict[goods_category].append(goods_name) ``` 3. 最后,可以输出每个分类下的商品列表,例如: ``` for category, goods_list in goods_dict.items(): print(category) print('-' * 20) for goods in goods_list: print(goods) print() ``` 输出结果如下: ``` 家电 -------------------- 电视机 洗衣机 数码产品 -------------------- 手机 平板电脑 家居用品 -------------------- 床上用品 餐具 食品饮料 -------------------- 牛奶 巧克力 服装鞋帽 -------------------- 外套 运动鞋 美容护肤 -------------------- 面霜 洗面奶 ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值