原题链接:May The Best Pet Win
题目大意:给定 N 个动物的速度范围(用数组表示,最小速度数组 A[N],最大速度数组 B[N]),将这些动物分成两组 S 和 T 进行接力赛,两组完成比赛所用时间的最大差值用 maxdiff(S,T) 表示。目标:找出一种分组方式 S、T, 使得 maxdiff(S,T) 最小。
大致思路:对于一组给定的分组方式 S、T,由于 S 与 T 互补,故可设:A(T)=∑(A[i]) (i∈T) ,A(S)=∑(A[i]) (i∉T) ,B(T)=∑(B[i]) (i∈T) ,B(S)=∑(B[i]) (i∉T)。则对于这种分组来说最大差 maxdiff(S,T) = max(B(T)−A(S), B(S)−A(T))。利用 S、T 互补的特点,通过求出 A[] 数组的总和 sa,B[] 数组的总和 sb,还可以进一步简化为:maxdiff(S,T) = max(B(T)−(sa−A(T)), sb−B(T)−A(T)) = max(B(T)+A(T)−sa, sb−B(T)−A(T))。接着只需要枚举所有 B(T)+A(T) 的情况即可。
#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
#include <numeric>
using namespace std;
class MayTheBestPetWin {
public:
int calc(vector <int>, vector <int>);
};
int MayTheBestPetWin:: calc(vector<int> A, vector<int> B) {
int sa = accumulate(A.begin(), A.end(), 0);
int sb = accumulate(B.begin(), B.end(), 0);
int MAX = sa + sb;
vector<int> last(MAX + 1);
for (int s = 0; s <= MAX; s++) {
last[s] = max(s - sa , sb - s);
}
int n = A.size();
vector<int> curr(MAX + 1);
for (int t=1; t<=n; t++) {
for (int s = 0; s <= MAX; s++) {
int res = last[s];
if (s + A[t-1] + B[t-1] <= MAX) {
res = min(res, last[s + A[t-1] + B[t-1] ]);
}
curr[s] = res;
}
swap(last, curr);
}
return last[0];
}