题解

难度:中等难度

知识点:贪心 排序 数学逻辑

贪心选择

贪心选择性质是指所求问题的整体最优解可以通过一系列局部最优的选择,换句话说,当考虑做何种选择的时候,我们只考虑对当前问题最佳的选择而不考虑子问题的结果。这是贪心算法可行的第一个基本要素。贪心算法以迭代的方式作出相继的贪心选择,每作一次贪心选择就将所求问题简化为规模更小的子问题。

【注】对于一个具体问题,要确定它是否具有贪心选择性质,必须证明每一步所作的贪心选择最终导致问题的整体最优解对。当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性质。问题的最优子结构性质是该问题可用贪心算法求解的关键特征。

本题思路:

例:
3 -- n

2 2 3 –-存入动态数组h中

2 -- m

3 1 –存入动态数组w中

1.首先对数组h和数组w进行排序得:

2 2 3 –-数组h

1 3 –数组w

2.首先考虑需要最大巧克力的小朋友(i=n-1),需要的巧克力h[n-1],判断最大块(j=m-1)的巧克力w[m-1]是否可以满足他的需求,即:h[n-1]<=w[m-1]。

如果成立即把该巧克力分配给该小朋友count++;继续判断次大小朋友i—和次大巧克力j--。

如果不成立说明无法满足该小朋友需求,继续对下一个小朋友进行判断,即i--。

3.结束条件为:已经判断完所有小朋友或者所有巧克力已经分发完成,即:i<0||j<0。

【注】:为什么要首先满足需求最大的小朋友:

例如:小朋友需求为 3 2
现有的巧克力 3 2
如果首先将3的巧克力分配给2的小朋友,那么需求为3的小朋友只剩下2的巧克力,无法上台。由于一块巧克力只能分配给一个小朋友,最多的分发就是让选择最少的小朋友(所需巧克力最大者)先进行选择。

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int main(){
    vector<int> h,w; 
    int n,m,x ;
    cin>>n; 
    for(int i=0;i<n;i++){
        cin>>x;
        h.push_back(x);
    }
    cin>>m;
    for(int i=0;i<m;i++){
        cin>>x;
        w.push_back(x);
    }
    sort(h.begin(),h.end());
    sort(w.begin(),w.end());
    int i=n-1,j=m-1;
    int count=0;
    while(i>=0&&j>=0){
        if(h[i]<=w[i]){
            count++;
            i--;
            j--;
        }else{
            i--;
        }
    }
    cout<<count<<endl;
    return 0;  
}