This problem aims to compute \(\displaystyle \max (\sum h_i t_i)(\sum p_i t_i)\) with constraint \(\displaystyle \sum c_i t_i \leq d, \; t_i \geq 0\), is a classical nonlinear programming.(note that " You can acquire any combination of the troop types, even fractional, such that the total cost is no more than the amount you have to spend" in this problem, so \(x_i\) can be any non-negtive "real" number).
It is impossible to have a algorithm dealing with all nonlinear problem, we can only deal with it one (type) by one (type).
For this particular problem, Convex Hull Method or Convex Hull trick ("斜率优化"(Slope optimization) in Chinese) may be a good choose.
First we simply the above problem as \(\displaystyle \max (\sum a_i x_i)(\sum b_i x_i)\) with constraint \(\displaystyle \sum x_i \leq 1\).
Note that all \((\sum a_i x_i, \sum b_i x_i)\) form a Convex Hull of \((a_i, b_i)\), so the max point must belong to the side of Convex Hull. So just get the Convex Hull and computer on each side and we get the answer.
The convex function defined on the bounded closed convex set must obtain the maximum value at the boundary
This problem aims to compute \(\displaystyle \max \sum t_i x_i\) with constraint \(x_i \geq 0\) and \[
\begin{pmatrix}
p_{11} & \cdots & p_{1n} \\
\vdots & \ddots & \\
p_{m1} & \cdots & p_{mn}
\end{pmatrix}
\begin{pmatrix}
x_1 \\
\vdots \\
x_n
\end{pmatrix}
\leq
\begin{pmatrix}
w_1 \\
\vdots \\
w_n
\end{pmatrix}
\] , is a classical linear programmingby Simplex algorithm. You can find it in wikipedia or Code template here (sorry I only know this place which writed in chinese, you can find the code nevertheless)
#include<bits/stdc++.h> #define watch(x) std::cout << (#x) << " is " << (x) << std::endl using LL = longlong; using pii = std::pair<int, int>; using pll = std::pair<LL, LL>;
using VD = std::vector<double>; constdouble eps = 1e-10; constdouble inf = 1e10; // make sure that A = (I, A') and b >= 0, compute max cx VD simplexCore(VD c, std::vector<VD> A, VD b){ int n = A.size(), m = c.size(); std::vector<int> p(m); std::iota(p.begin(), p.end(), 0); for (int i = 0; i < n; ++i) A[i].emplace_back(b[i]); c.emplace_back(0); A.emplace_back(c); for (int j = n; j <= m; ++j) { for (int i = 0; i < n; ++i) { A[n][j] -= A[n][i] * A[i][j]; } } auto check = [&]() -> bool { for (int j = n; j < m; ++j) if (A[n][j] > eps) { bool flag = false; for (int i = 0; i < n; ++i) if (A[i][j] > eps) { flag = true; break; } if (!flag) returnfalse; } returntrue; }; while (1) { int ch = std::max_element(A[n].begin() + n, A[n].begin() + m) - A[n].begin(), hc; if (A[n][ch] < eps) break; if (!check()) { std::cout << "\nNo max solution!\n"; returnVD(); } double theta = DBL_MAX; for (int i = 0; i < n; ++i) if (A[i][ch] > eps && A[i].back() / A[i][ch] < theta) { theta = A[i].back() / A[i][ch]; hc = i; } std::swap(p[ch], p[hc]); double tmp = 1 / A[hc][ch]; for (int j = n; j <= m; ++j) A[hc][j] *= tmp; for (int i = 0; i <= n; ++i) if (i != hc) { for (int j = n; j <= m; ++j) if (j != ch) { A[i][j] -= A[i][ch] * A[hc][j]; } } for (int i = 0; i <= n; ++i) A[i][ch] *= -tmp; A[hc][ch] = tmp; } VD x(m); for (int i = 0; i < n; ++i) x[p[i]] = A[i].back(); // watch(-A.back().back()); // max_val return x; // point Corresponds to max_val } // compute max cx, with Aqx = bq and Alq x <= blq, end of 0 can be ommit in A and Aq VD simplex(VD c, std::vector<VD> Aq, VD bq, std::vector<VD> Alq, VD blq){ assert(Aq.size() == bq.size()); assert(Alq.size() == blq.size()); int n = Aq.size() + Alq.size(); int m = c.size(); for (int i = 0; i < bq.size(); ++i) if (bq[i] < -eps) { for (auto &x : Aq[i]) x = -x; bq[i] = -bq[i]; } for (int i = 0; i < blq.size(); ++i) if (blq[i] < -eps) { for (auto &x : Alq[i]) x = -x; ++m; } std::vector<VD> A(n, VD(n + m)); VD f(n + m), b(n); int now = n + c.size(); for (int i = 0; i < n; ++i) A[i][i] = 1; for (int i = 0; i < Aq.size(); ++i) { for (int j = 0; j < Aq[i].size(); ++j) A[i][n + j] = Aq[i][j]; b[i] = bq[i]; f[i] = -inf; } for (int i = 0; i < Alq.size(); ++i) { for (int j = 0; j < Alq[i].size(); ++j) A[i + Aq.size()][n + j] = Alq[i][j]; if (blq[i] < -eps) { A[i + Aq.size()][now++] = -1; f[i + Aq.size()] = -inf; } b[i + Aq.size()] = fabs(blq[i]); } for (int i = 0; i < c.size(); ++i) f[n + i] = c[i]; auto x = simplexCore(f, A, b); returnVD(x.begin() + n, x.begin() + n + c.size()); } intmain(){ // freopen("in","r",stdin); std::ios::sync_with_stdio(false); std::cin.tie(nullptr); int n, m; std::cin >> n >> m; std::vector<std::vector<double>> A(n, std::vector<double>(m, 0)); std::vector<double> b(n), c(m); for (auto &x : b) std::cin >> x; for (int j = 0; j < m; ++j) { for (int i = 0; i < n; ++i) std::cin >> A[i][j]; std::cin >> c[j]; } auto x = simplex(c, std::vector<VD>(), VD(), A, b); double ans = 0; for (int i = 0; i < m; ++i) ans += c[i] * x[i]; std::cout.precision(2); std::cout << std::fixed << ans * 100 << std::endl; return0; }