版权声明:欢迎转载,不要求署名~~~ https://blog.csdn.net/shadandeajian/article/details/82227595
传送门:题目
题意:
题意很难懂,而且问了四个问题。
先说一下背景,根据Braess的悖论,人们在去往某一条道路时总会选择耗费时间最少的道路(人们是很机智的),现在有n+1个城市,两边的城市是起点和终点,有且只有两条道路,每一条道路的的每一段都有一个权值,k代表压力指数,如果人们都选择这条道路,而不选择另一条道路,那么这条道路的压力指数k为1,否则为0,除了两边的起点和终点,中间的n-1座城市均为特殊城市,特殊城市的意思就是,该城市有个闸门,如果闸门开放,那么车可以从一条道路变道到另一条道路,如果不开放,那么就不允许变道。
现在问:
- 如果所有闸门开放,人们花费时间的平均值
- 如果所有闸门不开放,人们花费时间的平均值
- 人们花费时间的最小值
- 人们花费时间的最大值
题解:
显然,解决这个问题,我们要先知道k值是多少。题目中已经告诉了我们计算公式:
另一条道路
,显然,根据Braess悖论,得到:
解得:
好了,我们现在已经知道k的通式了,但是不要忘记,根据Braess悖论,上面通式的满足条件为
,不难想到,当一条道路时间足够小,即使k=1,人们也会全部选择这条道路,那么肯定的是,我们在计算时间的时候,只考录这条道路就好了,而且,这条道路的
。
现在考虑四个问题:
- 第一个问题,所有城市可以任意变道,那么他们的压力指数都是关联的,所有直接套个通式就能计算出
- 第二个问题,所有城市都不可以变道,那么他们的压力指数都是独立的,我们用个for循环分别计算就好了
- 第三个问题和第四个问题, 搜索过程中dp。
AC代码:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <iomanip>
#define debug(x) cout<<#x<<" = "<<x<<endl;
using namespace std;
const int maxn=5010;
const double INF=0x3f3f3f3f3f3f3f3f;
int a[maxn],b[maxn],c[maxn],d[maxn];
double ans1,ans2,ans3[maxn],ans4[maxn];
double solve(int start,int last){
int suma=a[last]-a[start];
int sumb=b[last]-b[start];
int sumc=c[last]-c[start];
int sumd=d[last]-d[start];
if(sumc+sumd<=sumb)
return sumc+sumd;
if(suma+sumb<=sumd)
return suma+sumb;
double k=(1.0*sumc+sumd-sumb)/(suma+sumc);
return k*suma+sumb;
}
int main(void){
freopen("braess.in","r",stdin);
freopen("braess.out","w",stdout);
int n,t1,t2,t3,t4;
cin>>n;
for(int i=1;i<=n;i++){
cin>>t1>>t2>>t3>>t4;
a[i]+=a[i-1]+t1;
b[i]+=b[i-1]+t2;
c[i]+=c[i-1]+t3;
d[i]+=d[i-1]+t4;
}
ans1=solve(0,n);
for(int i=1;i<=n;i++)
ans2+=solve(i-1,i);
for(int i=1;i<=n;i++){
ans3[i]=INF;
ans4[i]=0;
for(int j=0;j<i;j++){
ans3[i]=min(ans3[i],ans3[j]+solve(j,i));
ans4[i]=max(ans4[i],ans4[j]+solve(j,i));
}
}
cout<<fixed<<setprecision(10)<<ans1<<endl<<ans2<<endl<<ans3[n]<<endl<<ans4[n]<<endl;
return 0;
}