商品交易

题目

小明下个月要去欧洲各国考察一遍,采购神秘石并从中搞点儿油水。
小明会按顺序依次经过序号分别为1,2,3,...,n的欧洲国家,在第i个国家神秘石的价格为Ai欧。整个行程中,当经过第i个国家时,小明只能花费Ai欧买入一块神秘石,或者卖出一块神秘石赚入Ai欧,或者什么都不做。整个行程中小明手中最多只能拥有1块神秘石,那么整个行程,小明从中获利最多多少欧,获得最多收益的同时,最少需要交易多少次?

输入

第一行一个数n(1<=n<=1e5);
第二行n个数,分别是Ai(1<=Ai<=1e9)。

输出

共一行,两个数,分别代表最大收益和对应的最少交易次数。

样例输入

5
9 7 10 1 5

样例输出

7 4

代码

#include 
#include 
#include 

using namespace std;

int n;
vector A;
map > max_val, min_time;

pair solute(int in_idx, int out_idx) {
    pair ans;

    auto it = max_val.find(in_idx);
    if (it != max_val.end() && (*it).second.find(out_idx) != (*it).second.end()) {
        ans.first = max_val[in_idx][out_idx];
        ans.second = min_time[in_idx][out_idx];
        return ans;
    }

    int one_val = 0, one_time = 0; 
    for (int i = in_idx; i < out_idx; ++i) for (int j = i + 1; j <= out_idx; ++j) {
        if (one_val < A[j] - A[i]) {
            one_val = A[j] - A[i];
            one_time = 1;
        }
    }

    int two_val = 0, two_time = 0;
    for (int mid = in_idx + 1; mid < out_idx; ++mid) {
        pair low = solute(in_idx, mid);
        pair high = solute(mid + 1, out_idx);
        if (two_val < low.first + high.first) {
            two_val = low.first + high.first;
            two_time = low.second + high.second;
        }
        else if (two_val == low.first + high.first 
                    && two_time > low.second + high.second) {
            two_time = low.second + high.second;
        }
    }
    
    if (one_val > two_val) {
        ans.first = one_val;
        ans.second = 1;
    }
    else {
        ans.first = two_val;
        ans.second = two_time;
    }

    max_val[in_idx][out_idx] = ans.first;
    min_time[in_idx][out_idx] = ans.second;
    return ans;
}

int main() {
    cin >> n;
    int in; for (int i = 0; i < n; ++i) { cin >> in; A.push_back(in); }
    
    pair ans = solute(0, n - 1);
    cout << ans.first << " " << ans.second * 2 << endl;
    return 0;
}

你可能感兴趣的:(商品交易)