牛客网习题集 - Wannafly挑战赛13- D applese生日

本文介绍了一种解决特定蛋糕分割问题的算法。该问题旨在通过最少的切割次数,将多个不同重量的蛋糕分割成若干份,使得最小块与最大块的重量比达到给定阈值。文章分析了解题思路,并给出了具体的实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

链接:点击打开链接

题目描述 

  最可爱的applese生日啦,他准备了许多个质量不同的蛋糕,想请一些同学来参加他的派对为他庆生,为了不让一部分同学感到不爽,他决定把每个蛋糕都分割成几份(也可以不分割),使得最小的蛋糕的质量与最大的蛋糕的质量的比值不小于一个值。但是applese的刀功并不是很好,所以他希望切尽量少的刀数使得所得到的蛋糕满足条件。由于applese为了保证每一块蛋糕的质量和期望的没有偏差,所以他一刀只能切下一块蛋糕,即将一块蛋糕分成两块,同时,他不能一刀同时切两块蛋糕,也就是说,applese一次只能将一块蛋糕分割成两块指定质量的蛋糕,这两块蛋糕的质量和应等于切割前的蛋糕的质量。Applese还急着准备各种派对用的饰品呢,于是他把这个问题交给了你,请你告诉他至少要切割几次蛋糕

输入描述:

第一行包括两个数T,n,表示有n个蛋糕,最小的蛋糕的质量与最大的蛋糕的质量的比值不小于T
接下来n行,每行一个数wi,表示n个蛋糕的质量

输出描述:

输出包括一行,为最小切割的刀数
数据保证切割次数不超过500
示例1

输入

0.99 3
2000 3000 4000

输出

6

备注:

0.5 < T < 1
1 <= n <= 1000
1 <= wi <= 1000000

题解:

        这题开始没做出来,因为感觉情况会非常的复杂,没有一点思路。但是看到了官方题解就很厉害了
        首先有一个结论,每块蛋糕分成的每一块的大小都是相同的
        基于这个结论,每次找到当前划分最大块所在的大块并将其划分数+1,
        检查是否满足题目的要求考虑这个结论为什么是正确的:考虑一个蛋糕切的刀数不变,那么可以想到假如分割得到的块是不同的,那么可能的献是增加最大和最小之间的差值,那么这样答案只会更劣,所以可以想到分成的每个块的大小是相同的那么只要按照上面模拟就可以了,这题妥妥的送温暖。
        基于这个思想,我使用了map
#include <bits/stdc++.h>
#define mp(a,b) make_pair(a,b)
using namespace std;

struct Node{
    double ave,all;
    int div;
}E[1007];

multimap<double,int> mp;
multimap<double,int>::iterator it,it2,i;

void show(){
    i = mp.begin();
    for (;i != mp.end();i ++){
        cout << i->first << ',' << i->second << endl;
    }
    cout << "****************************" << endl;
}

int main()
{
    ios::sync_with_stdio(false);

    double des;
    int n;

    cin >> des >> n;
    for (int i = 1;i <= n;i ++){
        cin >> E[i].all;
        E[i].div = 1;
        E[i].ave = E[i].all;
        mp.insert(mp(E[i].ave,i));
    }

    it = mp.begin();
    it2 = mp.end();it2--;

    //show();

    if (n == 1)cout << 0 << endl;
    else {
        int ans = 0;
        while (it->first/it2->first < des){
            int ID = it2->second;
            E[ID].div ++;
            E[ID].ave = E[ID].all/E[ID].div;
            mp.erase(it2);
            mp.insert(mp(E[ID].ave,ID));
            it2 = mp.end();it2--;
            it = mp.begin();
            ans ++;

            //show();
        }

        cout << ans << endl;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值