ARC128 C - Max Dot(贪心+构造)
目录
Description
有一个数组 \(a\), 要求构造一个数组 \(x\),满足 \(\sum{a_i*x_i}\) 最大
其中 \(x_i\) 的大小不超过 \(m\),而且 \(\sum{x_i}=S\),\(0<=x_1<=x_2<=....x_n<=m\)
State
\(1<=n<=5000\)
\(1<=m<=10^6\)
\(1<=S<=10^6\)
\(1<=a_i<=10^6\)
Input
3 2 3
1 2 3
Output
8.00000000000000000000
Solution
先考虑一种极端的情况, \(a\) 数组为降序,此时 \(x\) 数组每个数为 \(\frac{S}{n}\)
这是题目才有下手点,我们可以从后向前找 \(\frac{sum_i}{n-i+1}\) 的最大值,如果没有 \(m\) 的限制,\(x=\frac{S}{n-i+1}\) ,此时可以贪心验证一下正确性
如果 \(x>m\) 就令这一段的 \(x\) 为 \(m\),然后重复上述过程,直至 \(S=0\)
Code
const int N = 5e3 + 5;
int n, m, k, _;
int a[N];
double ans[N];
signed main()
{
// IOS;
double m, s;
while(~ sd(n)){
sf(m), sf(s);
rep(i, 1, n) sd(a[i]);
int st = n;
while(st > 0){
double sum = 0;
int pos;
double maxx = 0;
for(int i = st; i; i --){
sum += a[i];
if(sum / (st - i + 1) > maxx){
maxx = sum / (st - i + 1);
pos = i;
}
}
double now = min(m, s / (st - pos + 1));
for(int i = st; i >= pos; i --){
ans[i] = now;
s -= now;
}
if(s <= 0) break;
st = pos - 1;
}
double sum = 0;
for(int i = 1; i <= n; i ++){
sum += a[i] * ans[i];
}
pf(sum);
}
// PAUSE;
return 0;
}

浙公网安备 33010602011771号