Codeforces 100518B DP

版权声明:欢迎转载,不要求署名~~~ https://blog.csdn.net/shadandeajian/article/details/82227595

传送门:题目

题意:

题意很难懂,而且问了四个问题。
先说一下背景,根据Braess的悖论,人们在去往某一条道路时总会选择耗费时间最少的道路(人们是很机智的),现在有n+1个城市,两边的城市是起点和终点,有且只有两条道路,每一条道路的的每一段都有一个权值,k代表压力指数,如果人们都选择这条道路,而不选择另一条道路,那么这条道路的压力指数k1,否则为0,除了两边的起点和终点,中间的n-1座城市均为特殊城市,特殊城市的意思就是,该城市有个闸门,如果闸门开放,那么车可以从一条道路变道到另一条道路,如果不开放,那么就不允许变道。
现在问:

  • 如果所有闸门开放,人们花费时间的平均值
  • 如果所有闸门不开放,人们花费时间的平均值
  • 人们花费时间的最小值
  • 人们花费时间的最大值

题解:

显然,解决这个问题,我们要先知道k值是多少。题目中已经告诉了我们计算公式: A k + B 另一条道路 C k + D ,显然,根据Braess悖论,得到:
A k + B = C k + D

解得: k = C + D B A + B

好了,我们现在已经知道k的通式了,但是不要忘记,根据Braess悖论,上面通式的满足条件为 k [ 0 , 1 ] ,不难想到,当一条道路时间足够小,即使k=1,人们也会全部选择这条道路,那么肯定的是,我们在计算时间的时候,只考录这条道路就好了,而且,这条道路的 k = 1
现在考虑四个问题:

  • 第一个问题,所有城市可以任意变道,那么他们的压力指数都是关联的,所有直接套个通式就能计算出
  • 第二个问题,所有城市都不可以变道,那么他们的压力指数都是独立的,我们用个for循环分别计算就好了
  • 第三个问题和第四个问题, n 2 搜索过程中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;
}

猜你喜欢

转载自blog.csdn.net/shadandeajian/article/details/82227595