• [洛谷P1528] 切蛋糕


    洛谷题目链接:切蛋糕

    题目描述

    Facer今天买了n块蛋糕,不料被信息组中球球等好吃懒做的家伙发现了,没办法,只好浪费一点来填他们的嘴巴。他答应给每个人留一口,然后量了量每个人口的大小。Facer有把刀,可以切蛋糕,但他不能把两块蛋糕拼起来,但是他又不会给任何人两块蛋糕。现在问你,facer怎样切蛋糕,才能满足最多的人。(facer的刀很强,切的时候不会浪费蛋糕)。

    输入输出格式

    输入格式:

    第一行n,facer有n个蛋糕。接下来n行,每行表示一个蛋糕的大小。再一行一个数m,为信息组的人数,然后m行,每行一个数,为一个人嘴的大小。(1<=n<=50, 1<=m<=1024)

    输出格式:

    一行,facer最多可以填多少张嘴巴。

    输入输出样例

    输入样例#1:
    4
    30
    40
    50
    25
    10
    15
    16
    17
    18
    19
    20
    21
    25
    24
    30

    输出样例#1:
    7

    简述一下题意:给出(n)块蛋糕的大小和(m)个人要吃的量.现在只允许切蛋糕,求最多能满足多少人的需求.


    我们并不知道最终能满足多少人,但是很显然,肯定要优先满足需求较小的人.所以可以现将每个人的需求排个序,这样口的大小的数组就是单调的了.既然是单调的,就可以用二分来确定最多能否满足前mid个人.前mid个人能否满足直接爆搜就可以了.


    然而,这样并过不了,因为数据范围,这么搞是肯定要TLE的.所以我们可以考虑一下剪枝.

    • 因为口的大小是单调的,所以如果第(i)个人和第(i-1)个人的口大小相同,不能满足第(i)个人就不能满足第(i-1)个人.
    • 因为每次切都会有浪费(搜索过程中并不知道哪些一定可以作为浪费,但是如果第一个人都无法满足就一定是浪费了的),所以可以吧浪费的统计下来,那么如果蛋糕的总和减去浪费的总量小于前(mid)个人的口的大小,则不论怎么搜,都搜不出结果.
    • 然后就是在搜索的过程中可以先从第(mid)个开始往第一个搜,因为能满足第(mid)人的情况比较少,可以减少分支.
    #include<bits/stdc++.h>
    using namespace std;
    const int N=50+5;
    const int M=1024+5;
    
    int n, m, ans = 0, waste = 0;
    int cake[N], temp[N], sum = 0;
    int mouth[M], pre[M];
    
    bool dfs(int person,int pos,int mid){
        if(person == 0) return true;
        if(sum-waste < pre[mid]) return false;
        for(int i=pos;i<=n;i++){
    	    if(temp[i] < mouth[person]) continue;
    	    temp[i] -= mouth[person];
    	    if(temp[i] < mouth[1]) waste += temp[i];
    	    if(mouth[person] == mouth[person-1]){
    	        if(dfs(person-1,i,mid)) return true;
    	    }
    	    else if(dfs(person-1,1,mid)) return true;
    	    if(temp[i] < mouth[1]) waste -= temp[i];
    	    temp[i] += mouth[person];
        }
        return false;
    }
    
    bool check(int mid){
        memcpy(temp,cake,sizeof(temp));
        waste = 0; bool res = dfs(mid,1,mid);
        if(res) return true;
        return false;
    }
    
    int main(){
        //freopen("data.in","r",stdin);
        cin >> n;
        for(int i=1;i<=n;i++) cin >> cake[i], sum += cake[i];
        cin >> m;
        for(int i=1;i<=m;i++) cin >> mouth[i];
        sort(mouth+1 , mouth+m+1); sort(cake+1 , cake+n+1);
        for(int i=1;i<=m;i++) pre[i] = pre[i-1]+mouth[i];
        int l = 0, r = m, mid;
        while(pre[r] > sum) r--;
        while(l <= r){
    	    mid = (l+r>>1);
    	    if(check(mid)) l = mid+1, ans = mid;
    	    else r = mid-1;
        }
        printf("%d
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    Python
    Python
    Python
    Python
    Python
    《The Rise and Fall of Scala》scala的兴衰
    Scala核心编程_第05章_函数式编程
    IntelliJ IDEA scala的源码设置
    Scala核心编程_第04章 程序流程控制
    Scala核心编程_第03章_运算符
  • 原文地址:https://www.cnblogs.com/BCOI/p/8931681.html
Copyright © 2020-2023  润新知