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

  • 相关阅读:
    java事件处理(贪吃蛇)
    九九乘法表
    使用文件包含指令include
    jsp页面的基本构成
    软件测试博客

    成功职业女性处世的10大秘诀
    再见啦,冬冬妹
    网摘——杜晓眼眼中的尹珊珊:什么都要,什么都要得到
    网摘——事关“工程师思维”
  • 原文地址:https://www.cnblogs.com/cytus/p/7806466.html
Copyright © 2011-2022 走看看