zoukankan      html  css  js  c++  java
  • Evanyou Blog 彩带

      题目传送门

      理解题意:给定你一个学期的课程和教室数量以及教室之间的距离还有换教室成功的概率,求一个学期走的距离的期望最小值

      题目是有够恶心的,属于那种一看就让人不想刷的题目。。。很明显的动规,但是那个动规方程真的是感人肺腑。。。绝对是我见过的最长的动规转移方程。。

      状态还是非常好理解的,dp[ i ][ j ][ k ]表示到第 i 个时间段换了 j 次教室,第 j 次成功与否的最小期望路径,当然这里还需要用最短路优化(不用看,这么小的数据范围肯定是floyd),还是看代码吧,没什么好讲的,把那个长得感人肺腑的动规方程理解的就好做了:

    #include<bits/stdc++.h>
    #define maxx 305
    #define maxn 2012
    using namespace std;
    int n,m,v,e,c1[maxn],c2[maxn];
    double dp[maxn][maxn][2],ans;
    double f[maxx][maxx],p[maxn];
    int main()
    {
      cin>>n>>m>>v>>e;ans=0x3f3f3f3f;
      for(int i=1;i<=n;i++)scanf("%d",&c1[i]);
      for(int i=1;i<=n;i++)scanf("%d",&c2[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]=0x3f3f3f3f;
        f[j][i]=0x3f3f3f3f;
          }
      for(int i=1;i<=e;i++){
        int x,y;double w;
        scanf("%d%d%lf",&x,&y,&w);
        f[x][y]=min(f[x][y],w);
        f[y][x]=f[x][y];}//别忘了判重边
      for(int k=1;k<=v;k++)
        for(int i=1;i<=v;i++)
          for(int j=1;j<i;j++)
        if(f[i][j]>f[i][k]+f[k][j]){
        f[i][j]=f[i][k]+f[k][j];
        f[j][i]=f[i][j];}//floyd,不解释
      for(int i=1;i<=n;i++)
        for(int j=0;j<=m;j++)
          for(int k=0;k<=1;k++)
        dp[i][j][k]=0x3f3f3f3f;
      dp[1][0][0]=0.0;dp[1][1][1]=0.0;
      for(int i=2;i<=n;i++){
        for(int j=0;j<=i&&j<=m;j++){
          dp[i][j][0]=min(dp[i-1][j][0]+f[c1[i-1]][c1[i]],//状态:上一次不换,这一次不换
                  dp[i-1][j][1]+f[c2[i-1]][c1[i]]*p[i-1]  //上一次换成功
                  +f[c1[i-1]][c1[i]]*(1.0-p[i-1]));    //上一次失败
          if(j>=1)
        dp[i][j][1]=min(dp[i-1][j-1][0]+f[c1[i-1]][c2[i]]*p[i] //上一次不换,这一次换成功
                +f[c1[i-1]][c1[i]]*(1.0-p[i]),          //这一次失败  
                dp[i-1][j-1][1]+f[c2[i-1]][c2[i]]*p[i-1]*p[i]  //上一次换,两次都成功
                +f[c1[i-1]][c2[i]]*(1.0-p[i-1])*p[i]       //上一次失败,这一次成功
                +f[c2[i-1]][c1[i]]*p[i-1]*(1.0-p[i])       //上一次成功,这一次失败
                +f[c1[i-1]][c1[i]]*(1.0-p[i-1])*(1.0-p[i]));  //两次都失败
        }
      }
    //是不是长得感人肺腑???
    for(int i=0;i<=m;i++) for(int j=0;j<=1;j++) ans=min(ans,dp[n][i][j]);
        //找到最小期望路径 printf(
    "%.2lf",ans); return 0; }

    怎么样,是不是感人肺腑??QWQ

  • 相关阅读:
    20175122邱昕 网络对抗技术exp2后门的原理与实践
    2019-2020 20175122邱昕《网络对抗技术》Exp1 PC平台逆向破解
    day04 python——进程和线程
    day 03 python——面向对象编程进阶
    day02 python——面向对象进阶
    day01 python——面向对象编程基础
    day05
    day04 五层模型之间的通信过程及Linux的目录相关内容
    day03 计算机的性能及系统启动
    Linux入门终端命令
  • 原文地址:https://www.cnblogs.com/cytus/p/7806466.html
Copyright © 2011-2022 走看看