https://nanti.jisuanke.com/t/16616
因为无论如何都是最差情况,所以让两方胜利之后返还金额相等是坠好的
先枚举在哪里分段,设分段之前押黑方胜的资金为A,绿方胜资金为C,之后押黑方胜资金为B,绿方胜资金为D,分段之前黑方胜单位返还金额为p,分段之后为q,则有式子:(A+C)p+(B+D)q=(C+D)T,0<p<T,0<q<T
在满足上述式子的前提下要求Ap+Bq最小
将第一个式子用q表示p,带入目标函数,得到目标函数是一个关于p的一次函数,则最小值一定在两个端点取到,带入p的最大值和最小值,比较一下函数值即可,p的最大值是min(T,(C+D)*T/(A+C)),而p的最小值可有q的最大值带入第一个式子得到。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iomanip>
#define N 1000010
using namespace std;
double a[N],b[N];
int main()
{
int n;
scanf("%d",&n);
int i,j,x,y;
double tota=0,totb=0;
for(i=1;i<=n;i++)
{
scanf("%lf%lf",&a[i],&b[i]);
if(a[i]<1e-6&&b[i]<1e-6) {n--,i--;continue;}
tota+=a[i],totb+=b[i];
}
double T;
scanf("%lf",&T);
double A=0,B=tota,C=0,D=totb,p,q;
double ans=1e18;
for(i=1;i<n;i++)
{
A+=a[i];C+=b[i];B-=a[i];D-=b[i];
if(A<=D) p=T;
else p=(C+D)*T/(A+C);
q=((C+D)*T-(A+C)*p)/(B+D);
if(A*p+B*q<ans) ans=A*p+B*q;
if(B<=C) q=T;
else q=(C+D)*T/(B+D);
p=((C+D)*T-(B+D)*q)/(A+C);
if(A*p+B*q<ans) ans=A*p+B*q;
}
printf("%.2lf",ans);
}