• 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

  • 相关阅读:
    理解cookie和session机制
    http协议中connection头的作用
    [转]使用Wireshark来检测一次HTTP连接过程
    http协议学习系列
    xcode清空project list
    How To Use Git Source Control with Xcode in iOS 6
    iOS开发XCODE5 SVN配置 使用办法
    iOS申请证书,Certificates, Identifiers &Profiles 简介
    C#学习单向链表和接口 IList<T>
    halcon学习笔记——(7)HALCON标定后的二维测量
  • 原文地址:https://www.cnblogs.com/cytus/p/7806466.html
Copyright © 2020-2023  润新知