#include<stdio.h>
#include<iostream>
#include<string.h>
#include<ctype.h>
#include<math.h>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<functional>
#include<string>
#include<algorithm>
#include<time.h>
#include<bitset>
#define MS(x,y) memset(x,y,sizeof(x))
#define MC(x,y) memcpy(x,y,sizeof(x))
#define MP(x,y) make_pair(x,y)
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
typedef int Int;
template <class T> inline void gmax(T &a,T b){if(b>a)a=b;}
template <class T> inline void gmin(T &a,T b){if(b<a)a=b;}
using namespace std;
const int N=5005,M=0,L=0,Z=1e9+7,maxint=2147483647,ms31=522133279,ms63=1061109567,ms127=2139062143;
int n;
int a[N],b[N],c[N],d[N];
double ans1,ans2,ans3,ans4;
double minf[N],maxf[N];
double cnt(int st,int ed)
{
int A=a[ed]-a[st];
int B=b[ed]-b[st];
int C=c[ed]-c[st];
int D=d[ed]-d[st];
if(A+B<=D)return A+B;
if(C+D<=B)return C+D;
double k=1.0*(C+D-B)/(A+C);
return k*A+B;
}
void fre()
{
freopen("braess.in","r",stdin);
freopen("braess.out","w",stdout);
}
int main()
{
fre();
while(~scanf("%d",&n))
{
for(int i=1;i<=n;i++)
{
scanf("%d%d%d%d",&a[i],&b[i],&c[i],&d[i]);
a[i]+=a[i-1];
b[i]+=b[i-1];
c[i]+=c[i-1];
d[i]+=d[i-1];
}
ans1=cnt(0,n);
ans2=0;for(int i=1;i<=n;i++)ans2+=cnt(i-1,i);
for(int i=1;i<=n;i++)
{
minf[i]=1e18;
maxf[i]=0;
for(int j=0;j<i;j++)
{
gmin(minf[i],minf[j]+cnt(j,i));
gmax(maxf[i],maxf[j]+cnt(j,i));
}
}
printf("%.10f %.10f %.10f %.10f\n",ans1,ans2,minf[n],maxf[n]);
}
return 0;
}
/*
【题意】
http://codeforces.com/gym/100518/attachments/download/2791/20132014-summer-petrozavodsk-camp-andrew-stankevich-contest-44-asc-44-en.pdf
不要惧怕难读难懂的题意,因为比赛的时候题目往往更难读(甚至还有极小可能题意出错)
有两个城市A,B,它们之间被两条路联通。
这两条路之间有n-1个交错口,但是这个交错口还未打开,也就是说,我们还不能从一条路切换到另外一条路。
对于第一条路,经过第i段所需的时间为ai*ki1+bi
对于第二条路,经过第i段所需的时间为ci*ki2+di
对于每个i,都有ki1+ki2=1。就是说,司机不从第一条路通过的话,就必然要从第二条路通过。
定义平衡时间为,有无限司机不停地从A到B,每个司机都会观察之前的司机行进方案与时间,选择自己的决策。
在最后不再发生变化的,司机从A到B的时间,就是平衡时间。
现在政府还可以选择,对于每个交错口,是否进行打开。
一旦打开,车就可以在这个交错口,开上第一条路或者第二条路。
现在问你——
1,不打开任一交错口的平衡时间
2,所有交错口都打开的平衡时间
3,最小平衡时间
4,最大平衡时间
【类型】
DP
【分析】
我们发现,如果打开一个交错口,事实上就相当于把A-B变成了A-C-B这样可以线性叠加的两段(A->B)与(A->C)
于是我们先设想如何解决子问题。
子问题是指不存在岔路口,走两条路的比例是一直确定的。那么——
对于第一条路,走的时间就是∑b[]+k*∑a[]
对于第二条路,走的时间就是∑d[]+(1-k)*∑c[]
我们要使得两者相等,即∑b[]+k*∑a[]=∑d[]+(1-k)*∑c[]
即得到:∑b[]+k*∑a[]=∑d[]+∑c[]-k*∑c[]
即得到:k*(∑a[]+∑c[])=∑d[]-∑b[]+∑c[]
然后我们可以解得:k=(∑d[]-∑b[]+∑c[])/(∑a[]+∑c[])
但是有一个限制,k∈[0,1],而且还要有分母不能为零。
然而我们只要给定一个判断,就可以筛掉这些状况——
if(A+B<=D)return A+B;
if(C+D<=B)return C+D;
然后就可以求得k,再接下来就可以直接输出答案
【时间复杂度&&优化】
O(n^2)
【trick】
【数据】
input
2
40 0 0 45
0 45 40 0
output
65.0
80.0
65.0
80.0
*/
【ASC44B】【DP】Braess's Paradox 分阶段思想

最新推荐文章于 2023-12-07 13:14:17 发布
