阿里巴巴笔试 2020.4.29

1、有n种不同口味的水果,第i种水果的数量为ai,现在需要把水果分给m个人,分给每个人水果的数量必须是相等的,并且每个人只能选择一种水果。问每个人最多能分到多少个水果。

【分析】二分答案转判定

#include 
using namespace std;

long long a[1000000+50];
long long n,m;
bool check( long long mid, long long m)
{
    long long num = 0;
    for(long long i=0; i<n; i++)
    {
        num += a[i]/mid;
    }
    if(num>=m)
        return true;
    return false;
}
int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        cin>>n>>m;
        long long sum = 0;
        for(int i=0; i<n;i++)
        {
            cin>>a[i];
            sum += a[i];
        }
        long long l = 1;
        long long r = sum;
        long long ans = 0;
        while(l<=r)
        {
            long long mid = (l+r)/2;
            if(check(mid,m))
            {
                ans = mid;
                l = mid + 1;
            }
            else{
                r = mid - 1;
            }
        }
        cout<<ans<<endl;
    }
}

/**
2
3 5
1 3 1
*/
2、有n头牛要吃糖,每个牛吃ai个糖,然后有一部分牛是两两配对的,如果一个吃了,另外一个也要吃,给出m个糖,问最多有几头牛能吃上糖。

分析: 当时很傻逼,想的是把小牛分成两类:成对的牛牛bk = ai+aj和单独的牛牛ai。分别对a(单独的牛牛)和b排序。维护指向a的指针,和指向b的指针。比较a的前2个之和与当前最小的b,取最小的那个。好吧0分,我人都傻了。

后来师兄告诉我说,直接把配对的绑在一起,然后糖是背包容量,牛的个数是价值。

#include 
using namespace std;
const int maxn = 1000000+50;
int a[maxn], w[maxn], v[maxn], vis[maxn];
int dp[maxn];
int n,m,k,cnt=1;

int main()
{
    cin>>n>>m;
    for(int i=1; i<=n ;i++)
        cin>>a[i];
    cin>>k;
    for(int i=0; i<k; i++)
    {
        int la, lb;
        cin>>la>>lb;
        vis[la] = vis[lb] = 1;
        v[cnt] = 2;
        w[cnt++] = a[la] + a[lb];
    }
    for(int i=1; i<=n; i++)
        if(vis[i]==0)
            v[cnt] = 1, w[cnt++] = a[i];

    for(int i=1; i<=cnt; i++)
    {
        for(int j=m; j>=w[i]; j--)
            dp[j] = max(dp[j], dp[j-w[i]]+v[i]);
    }

    cout<<dp[m]<<endl;
}

你可能感兴趣的:(面经,笔试)