Official

E - Maximize Rating Editorial by en_translator


In the expression of rating,

\[ R=\frac{\sum_{i=1}^k (0.9)^{k-i}Q_i}{\sum_{i=1}^k (0.9)^{k-i}}-\frac{1200}{\sqrt{k}}, \]

when \(k\) is fixed, if you choose different contests, only \(\displaystyle \sum_{i=1}^k (0.9)^{k-i}Q_i\) part changes, and this value is linear with respect to the chosen values. Therefore, once we obtain \(M(k) = \) the maximum possible \(\displaystyle \sum_{i=1}^k (0.9)^{k-i}Q_i\) for each \(k=1,2,\ldots,N\), then the answer can be obtained as

\[ \max_{1\leq k\leq N} \left( \frac{M(k)}{\sum_{i=1}^k (0.9)^{k-i}}-\frac{1200}{\sqrt{k}}\right). \]

Thus, it is sufficient to find the maximum \(\displaystyle \sum_{i=1}^k (0.9)^{k-i}Q_i\) when choosing \(k\) contests out of the \(N\), for each \(k=1,2,\ldots,N\).

These value can be found by Dynamic Programming (DP).
Let \(dp[i][j]\) \((1\leq j\leq i\leq N)\) be the maximum \(\displaystyle \sum_{k=1}^j (0.9)^{j-k}Q_k\) when choosing \(j\) contests out of the first \(i\) contests (where \((Q_1,Q_2,\ldots,Q_j)\) is the performances of the chosen contests in the order of participation). What we want is \((1\leq j\leq N)\).

Obviously, \(dp[1][1]\) equals \(P_1\).
Now, suppose that we know \(dp[i-1][j']\) \((1\leq j\leq i-1)\), and consider how to evaluate \(dp[i][j]\).

Among the way to choose \(j\) contests out of the first \(i\), for those which do not contain the \(i\)-th contests, the maximum \(\displaystyle \sum_{k=1}^j (0.9)^{j-k}Q_j\) equals \(dp[i-1][j]\). (Exception is when \(j=i\), where all the contests must be chosen and this is not the case.)

For a way that do contain the \(i\)-th contest, the rating value for the chosen combination can be expressed as

\[ \sum_{k=1}^j (0.9)^{j-k}Q_k=\sum_{k=1}^{j-1} (0.9)^{j-k}Q_k+P_i =0.9\sum_{k=1}^{j-1} (0.9)^{(j-1)-k}Q_k+P_i. \]

Here, \((Q_1,Q_2,\ldots,Q_{k-1})\) must be chosen from the performances of the first \((i-1)\) contests without changing the order, so the maximum possible \(\displaystyle \sum_{k=1}^{j-1} (0.9)^{(j-1)-k}Q_k\) coincides with \(dp[i-1][j-1]\). (Exception is when \(j=1\), where \(\displaystyle \sum_{k=1}^{j-1} (0.9)^{(j-1)-k}Q_k=0\).)

Hence, we have

\[ dp[i][j]= \begin{cases} \max(dp[i-1][1],P_i) & (\text{if }j=1) \\ \max(dp[i-1][j],0.9\times dp[i-1][j-1]+P_i) & (\text{if }2\leq j\leq i-1) \\ 0.9\times dp[i-1][i-1]+P_i & (\text{if }j=i). \end{cases} \]

Regarding the time complexity, each \(dp[i][j]\) can be obtained from \(dp[i-1][j]\) and \(dp[i-1][j-1]\) in \(O(1)\) time, for a total of \(O(N^2)\) time. The answer can be obtained from the values \(dp[N][j]\) in \(O(N)\) time, so the problem can be solved in a total of \(O(N^2)\) time, which is fast enough.
Thus, the problem has been solved.

Another solution (backtracking DP)

Again, we want to find the maximum \(\displaystyle \sum_{i=1}^k (0.9)^{k-i}Q_i\) when choosing \(k\) contests out of the \(N\) for each \(k=1,2,\ldots,N\).

We define the DP as follows: let \(dp[i][j]\) \((1\leq i,j\leq N,j\leq N-i+1)\) be the maximum \(\displaystyle \sum_{k=1}^j (0.9)^{j-k}Q_k\) when choosing \(j\) contests out of the \(i\)-th through the \(N\)-th contests (where \((Q_1,Q_2,\ldots,Q_j)\) are the performances of the chosen contests in the order of participation).

Then we have the following relations: \(dp[N][1]=P_N\) and

\[ dp[i][j]= \begin{cases} \max(dp[i+1][1],P_i) & (\text{if }j=1) \\ \max(dp[i+1][j],dp[i+1][j-1]+(0.9)^{j-1}\times P_i) & (\text{if }2\leq j\leq N-i) \\ dp[i+1][N-i]+0.9^{N-i}\times P_i & (\text{if }j=N-i+1). \end{cases} \]

The derivation is almost the same as before, so omit the details. By precomputing \(0.9^k\) for each \(k=0,1,\ldots,N\), we can solve the problem in a total of \(O(N^2)\) time again.

Sample code in C++:

#include <bits/stdc++.h>
using namespace std;
int main(void){
	const double c=0.9;
	int n;
	cin>>n;
	vector<double>p(n);
	vector<double>dp(n+1,0);
	double w,ans=-1200.0;
	for(int i=0;i<n;i++)cin>>p[i];
	for(int i=0;i<n;i++){
		dp[i+1]=c*dp[i]+p[i];
		for(int j=i-1;j>=0;j--){
			dp[j+1]=max(c*dp[j]+p[i],dp[j+1]);
		}
	}
	w=0.0;
	for(int i=1;i<=n;i++){
		w=c*w+1.0;
		ans=max(ans,dp[i]/w-1200.0/sqrt((double)i));
	}
	cout<< std::fixed << std::setprecision(10) <<ans<<endl;
	return 0;
}

posted:
last update: