[Luogu P1528] Cut the cake

Lo Valley Topic Link: Cut the Cake

Topic description

Facer bought n pieces of cake today, but unexpectedly, it was discovered by the lazy guys in the message group, such as Qiuqiu. He promised to leave a mouthful for each, and then measured the size of each population. Facer has a knife and can cut a cake, but he can't put two cakes together, but he won't give anyone two cakes. Now I ask you, how does facer cut the cake in order to satisfy the most people. (The facer's knife is strong and doesn't waste the cake when cutting).

Input and output format

Input format:

In the first row n, facer has n cakes. Next n lines, each line represents the size of a cake. Another line is a number m, which is the number of people in the information group, and then m lines, each line is a number, which is the size of a person's mouth. (1<=n<=50, 1<=m<=1024)

Output format:

In one line, the maximum number of mouths the facer can fill.

Input and output example

Input Sample #1:
4
30
40
50
25
10
15
16
17
18
19
20
21
25
24
30

Sample output #1:
7

Briefly describe the meaning of the question: give the size of \(n\) cake and the amount of \(m\) that individuals want to eat. Now only cakes are allowed to be cut, and how many people can be satisfied at most.


We do not know the final How many people can be satisfied, but obviously, people with smaller needs must be satisfied first. Therefore, we can now rank the needs of each person, so that the array of the size of the mouth is monotonic. Since it is monotonic, we can use dichotomous To determine whether it can satisfy the former mid individual at most. Whether the former mid individual can satisfy the direct explosion search is enough.


However, this will not pass, because of the data range, this will definitely require TLE. So we can consider pruning.

  • Because the size of the mouth is monotonic, if the mouth size of the \(i\)th person and the \(i-1\)th person is the same, it cannot satisfy the \(i\)th person and cannot satisfy the \(i-1 \) individual.
  • Because there will be waste every time you cut (I don't know which ones can be considered waste during the search process, but if the first person can't satisfy it, it must be waste), so you can count the waste, then if the sum of the cakes If the total amount minus the waste is less than the size of the mouth of the former \(mid\) individual, no matter how you search, you will not find results.
  • Then, in the process of searching, you can start from the \(mid\) to the first search, because there are fewer cases that can satisfy the \(mid\) person, which can reduce branches.
#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\n",ans);
    return 0;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324781178&siteId=291194637
cut