zoukankan      html  css  js  c++  java
  • AcWing 233. 换教室 (期望DP+floyd)打卡

    题目:https://www.acwing.com/problem/content/235/

    题意:有n个时间段,这个时间段有两个地方授课ci,di,最开始是在ci,可以申请去di,但是是几率的,然后有x个教室,y条道路,还有k个机会申请,可以申请<=k次,最后求怎么样的申请求的期望值最低,求那个最低值

    思路:这个题我们首先先求一遍floyd,为了方便后面的操作,我们其实很容易看出这是一个dp,什么可以选k次这些都是惯用套路,这个题其实就只用分两种状态,每个时间段申请或者不申请,所以我们的dp数组就可以写成 dp[i][j][k]    ,i是代表是第几个时间段,j是代表申请了j次,k只有0/1代表申请不申请,最后我们要留意的是,转移方程这里,因为申请是有几率申请成功的,所以我们要考虑是否申请成功,所以要记录两种状态,如果连续两次都申请的话那就要用到乘法原理变成四种情况,然后转移即可

    #include<bits/stdc++.h>
    #define maxn 100005
    #define mod 1000000007
    using namespace std;
    double p[10001],f[2001][2001],dp[2001][2001][2];
    int a[2001][2001],c[20001],d[20001];
    int main()
    {
        int n,m,v,e,a1,b1,c1;
        cin>>n>>m>>v>>e;
        for(int i=1;i<=n;i++)scanf("%d",&c[i]);
        for(int i=1;i<=n;i++)scanf("%d",&d[i]);
        for(int i=1;i<=n;i++)scanf("%lf",&p[i]);
        
        for(int i=1;i<=v;i++)
         for(int j=1;j<i;j++)
          f[i][j]=f[j][i]=999999999;
       
        for(int i=1;i<=e;i++){
            scanf("%d%d%d",&a1,&b1,&c1);
            f[a1][b1]=f[b1][a1]=min(f[a1][b1],(double)c1);
        }
        
        for(int k=1;k<=v;k++)
          for(int i=1;i<=v;i++)
            for(int j=1;j<i;j++)
              if(f[i][k]+f[k][j]<f[i][j])
                 f[i][j]=f[j][i]=f[i][k]+f[k][j];
                 
        for(int i=1;i<=n;i++)
            for(int j=0;j<=m;j++)
                dp[i][j][0]=dp[i][j][1]=999999999;
         
        dp[1][0][0]=dp[1][1][1]=0;
        for(int i=2;i<=n;i++){
         double add1=f[c[i-1]][c[i]];
          for(int j=0;j<=min(m,i);j++)
           {                     
              dp[i][j][0]=min(dp[i-1][j][0]+add1,dp[i-1][j][1]+f[d[i-1]][c[i]]*p[i-1]+f[c[i-1]][c[i]]*(1-p[i-1]));//不申请   由前面是否申请来推出后面
              if(j!=0)//乘法原理计算四种情况
              dp[i][j][1]=min(dp[i-1][j-1][0]+f[c[i-1]][d[i]]*p[i]+f[c[i-1]][c[i]]*(1-p[i]),dp[i-1][j-1][1]+f[c[i-1]][c[i]]*(1-p[i-1])*(1-p[i])+f[c[i-1]][d[i]]*(1-p[i-1])*p[i]+f[d[i-1]][c[i]]*(1-p[i])*p[i-1]+f[d[i-1]][d[i]]*p[i-1]*p[i]);
           }   
        }          
                                   
        double hahaha=9999999999;
        for(int i=0;i<=m;i++){
        hahaha=min(dp[n][i][0],min(dp[n][i][1],hahaha));}
        printf("%.2lf",hahaha);
    }
  • 相关阅读:
    POJ 1015 Jury Compromise【DP】
    POJ 1661 Help Jimmy【DP】
    HDU 1074 Doing Homework【状态压缩DP】
    HDU 1024 Max Sum Plus Plus【DP,最大m子段和】
    占坑补题。。最近占的坑有点多。。。
    Codeforces 659F Polycarp and Hay【BFS】
    Codeforces 659E New Reform【DFS】
    Codeforces 659D Bicycle Race【计算几何】
    廖大python实战项目第四天
    廖大python实战项目第三天
  • 原文地址:https://www.cnblogs.com/Lis-/p/11301928.html
Copyright © 2011-2022 走看看