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);
    }
  • 相关阅读:
    利用多线程对数组进行归并排序
    Java.nio-随机读写汉字
    用Java语言实现简单的词法分析器
    python全栈闯关--5-字典
    python全栈闯关--XX-细节总结汇总
    linux温故--1-daily_routine
    python全栈闯关--4-列表和元祖
    saltstack-6 pillar组件
    saltstack-5 grainx组件
    saltstack-4 常用模块api调用
  • 原文地址:https://www.cnblogs.com/Lis-/p/11301928.html
Copyright © 2011-2022 走看看