360 2018秋招笔试题

360 2018秋招笔试题

(后面再更新代码…)

1、卖粉笔

小明有m根彩色粉笔和n根白色粉笔,其中a根彩色粉笔和b根白色粉笔可以卖x元,c根白色粉笔可以卖y元,d根彩色铅笔可以卖z元,粉笔不一定要卖完,如何使利益最大?

举例:

输入:
m=5, n=5, a=1, b=2, c=3, d=3, x=2, y=1, z=3,
输出:
7

解析:

递归搜索。共有三种卖的方式:
[a , b] —> x
[0, c] —> y
[d, 0] —> z
每次都从这三种方式中选择一个利益最多的方式,剩下的粉笔继续递归搜索,直至卖完或者卖不出去了。

c++代码实现:

#include <iostream>
#include <vector>
#include <map>
using namespace std;

int sell(vector<int>& objects,vector<vector<int>>& special,map<vector<int>,int>& answer)
{
    if(answer.find(objects)!=answer.end())
        return answer[objects];
    int result = 0, j = 0;
    for(vector<int> s : special) {
        vector<int> rest(objects.begin(),objects.end());
        for( j=0; j<objects.size(); j++) {
            int diff = rest[j]-s[j];
            if(diff<0)
                break;
            rest[j] = diff;
        }
        if(j==objects.size()) {
            int money = s[j] + sell(rest,special,answer);
            result = money > result ? money : result;
        }
    }
    answer[objects] = result;
    //没卖完的,返回0
    return result;
}

int shoppingOffer(vector<int>& objects,vector<vector<int>>& special)
{
    map<vector<int>,int> answer;
    return sell(objects,special,answer);
}

int main()
{
    int m,n,a,b,c,d,x,y,z;
    cin>>m>>n>>a>>b>>c>>d>>x>>y>>z;
    vector<vector<int>> special = {{a,b,x},{0,c,y},{d,0,z}};
    vector<int> objects = {m,n};
    cout<<shoppingOffer(objects,special)<<endl;
    return 0;
}

2、数组交换

有两个数组,分别是a[a1, a2, …, an]和b[b1, b2, …, bm],sum表示数组所有的元素和,最多交换a和b数组中两对数字,使得;两个交换后的的数组的sum的差值的绝对值最小?

举例:

输入:
n=4, a= [1, 3, 7, 9], m=3, b=[2, 10, 12]
输出:
0
解释:交换(3,2)和(9,12)两对,最后两个数组的元素和都为22。差值的绝对值即为0。

解析:

先来看这个问题,交换两个数组的某对元素,使得两个数组的元素和差值的绝对值最小,这个问题比上面的问题少了一个限制:元素的交换次数不限制
数组a,元素和记为sumA;数组b,元素和记为sumB。
如果sumA==sumB,则不用交换。
不失一般性的,我们假设sumA > sumB,delta = sumA-sumB。
假设a[i]与b[j]交换,则:sumA’=sumA-a[i]+b[j], sumB’=sumB-b[j]+a[i]
delta’ = sumA’-sumB’ = delta - 2*(a[i]-b[j])。
因此,要使得两个数组元素和尽可能相等,则delta’尽可能等于0,应使a[i]-b[j]尽可能接近delta/2。
但是本题有限制,最多交换两次。目前方法还没想出来。

C++代码实现:
交换两个数组的某对元素,使得两个数组的元素和差值的绝对值最小

#include <iostream>
#include <math.h>
using namespace std;

int change(int a[],int n,int b[],int m,int sumA,int sumB)
{
    int delta = 0;
    bool bigger = true;
    if(sumA>sumB){
        delta = sumA - sumB;
        bigger = true;
    }
    else{
        delta = sumB - sumA;
        bigger = false;
    }
    int diff = 0, x=0;
    for(int i=0; i<n; i++) {
        for(int j=0; j<m; j++) {
            diff = a[i]-b[j];
            x = diff > 0 ? diff : (~diff+1); //abs(diff)
            if((x*2 <= delta)&&((bigger && diff>0)||(!bigger && diff<0))){
               a[i] ^= b[i];
               b[i] = a[i]^b[i];
               a[i] = a[i]^b[i];   //交换a[i] b[j]
               delta -= 2*x;
               if(delta==0)
                    return 0;
            }
        }
    }
    return delta;
}

int main()
{
    int n,m,sumA=0,sumB=0;
    cin>>n;
    int a[n];
    for(int i=0; i<n; i++){
        cin>>a[i];
        sumA += a[i];
    }

    cin>>m;
    int b[m];
    for(int i=0; i<m; i++){
        cin>>b[i];
        sumB += b[i];
    }
    if(sumA==sumB)
        cout<<0;
    else
        cout<<change(a,n,b,m,sumA,sumB);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/peaktravel/article/details/77607662